You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django视图中获取动态数据表行并转为Pandas DataFrame

Solution: Collect Dynamic Table Data into Pandas DataFrame in Django

The main issue here is that contenteditable <td> elements aren't automatically included in form submissions, and your other row fields (date, availability, etc.) aren't being sent either. Here's how to fix this and get all row data into a Pandas DataFrame:


Step 1: Modify the Template to Include Submittable Fields

We'll add hidden inputs for every row field (including the editable "Advised Price") and use JavaScript to sync the contenteditable cell with its corresponding hidden input.

Updated Template Code

<form action="{%url 'livedb_model:validation' property.id roomtype.id %}?normal_price={{normal_price}}&week_day_multi={{week_day_multi}}&week_end_multi={{week_end_multi}}&max_discount={{max_discount}}&max_markup={{max_markup}}&coccCategory={{coccCategory}}&agressiveness={{agressiveness}}" method="post"> 
    {% csrf_token %} 
    <input class='btn btn-primary btn-large btn-block align-self-center'type='submit' value='submit'> 
    <div id="datatable" class="table-editable align-self-stretch"> 
        <table class="table table-bordered table-responsive-md table-striped text-center"> 
            <tr> 
                <th class="text-center">Date</th> 
                <th class="text-center">Availability</th> 
                <th class="text-center">Current Price</th> 
                <th class="text-center">Current Occupancy</th> 
                <th class="text-center">Advised Price</th> 
            </tr> 
            {% for day in invdf.itertuples %} 
            <tr> 
                <td class="pt-3-half">{{day.date|date:'M d,Y'}}</td> 
                <td class="pt-3-half">{{day.allotment}}</td> 
                <td class="pt-3-half">{{day.price|floatformat:2}}</td> 
                <td class="pt-3-half">{{day.occupancy|floatformat:2}}</td> 
                <td class="pt-3-half price-advised" contenteditable="true">{{day.price_advised|floatformat:2}}</td>
                
                <!-- Hidden inputs to submit row data -->
                <input type="hidden" name="dates[]" value="{{day.date|date:'Y-m-d'}}">
                <input type="hidden" name="allotments[]" value="{{day.allotment}}">
                <input type="hidden" name="current_prices[]" value="{{day.price|floatformat:2}}">
                <input type="hidden" name="occupancies[]" value="{{day.occupancy|floatformat:2}}">
                <input type="hidden" name="advised_prices[]" class="advised-price-input" value="{{day.price_advised|floatformat:2}}">
            </tr> 
            {% endfor%} 
        </table>
    </div> 
</form>

<!-- JavaScript to sync contenteditable cell with hidden input -->
<script>
document.addEventListener('DOMContentLoaded', function() {
    const priceCells = document.querySelectorAll('.price-advised');
    
    priceCells.forEach(cell => {
        // Sync on blur (when user finishes editing)
        cell.addEventListener('blur', function() {
            const hiddenInput = this.closest('tr').querySelector('.advised-price-input');
            hiddenInput.value = this.textContent.trim();
        });
        
        // Optional: Sync on input for real-time updates
        cell.addEventListener('input', function() {
            const hiddenInput = this.closest('tr').querySelector('.advised-price-input');
            hiddenInput.value = this.textContent.trim();
        });
    });
});
</script>

Step 2: Update the Django View to Process the Data

Now, when the form is submitted, all row data will be sent as lists in the POST request. We'll collect these lists, convert them to appropriate data types, and create a Pandas DataFrame.

Updated View Code

import datetime
import pandas as pd
from django.http import HttpResponse

def validation(request, id, rt_id):
    if request.method == 'POST':
        # Collect all submitted row data from POST
        dates_raw = request.POST.getlist('dates[]')
        allotments_raw = request.POST.getlist('allotments[]')
        current_prices_raw = request.POST.getlist('current_prices[]')
        occupancies_raw = request.POST.getlist('occupancies[]')
        advised_prices_raw = request.POST.getlist('advised_prices[]')
        
        # Convert raw data to proper types (handle potential errors)
        data = {
            'date': [],
            'allotment': [],
            'price': [],
            'occupancy': [],
            'price_advised': []
        }
        
        for i in range(len(dates_raw)):
            # Parse date
            try:
                date = datetime.datetime.strptime(dates_raw[i], '%Y-%m-%d').date()
                data['date'].append(date)
            except ValueError:
                continue  # Skip invalid dates
            
            # Parse allotment (integer)
            try:
                allotment = int(allotments_raw[i])
                data['allotment'].append(allotment)
            except ValueError:
                data['allotment'].append(None)
            
            # Parse prices/occupancy (floats)
            try:
                price = float(current_prices_raw[i])
                data['price'].append(price)
            except ValueError:
                data['price'].append(None)
            
            try:
                occupancy = float(occupancies_raw[i])
                data['occupancy'].append(occupancy)
            except ValueError:
                data['occupancy'].append(None)
            
            try:
                advised_price = float(advised_prices_raw[i])
                data['price_advised'].append(advised_price)
            except ValueError:
                data['price_advised'].append(None)
        
        # Create Pandas DataFrame
        df = pd.DataFrame(data)
        
        # Now you can use df as needed (save to DB, perform calculations, etc.)
        print(df.head())  # Example: print first 5 rows
        
        return HttpResponse("Data successfully processed! Check console for DataFrame preview.")
    
    # Handle GET request (render the form with your existing invdf logic)
    else:
        # Your existing code to generate invdf and render the template
        # ...

Alternative: Regenerate Original Data + Update Advised Prices

If you can regenerate the original invdf DataFrame using the query parameters from the URL, you can avoid sending redundant data. Here's how:

Modified Template (Only Hidden Input for Advised Price)

<!-- In each row -->
<td class="pt-3-half price-advised" contenteditable="true">{{day.price_advised|floatformat:2}}</td>
<input type="hidden" name="advised_price_{{day.date|date:'Y-m-d'}}" class="advised-price-input" value="{{day.price_advised|floatformat:2}}">

Modified View Code

def validation(request, id, rt_id):
    if request.method == 'POST':
        # Get query parameters to regenerate invdf
        normal_price = float(request.GET.get('normal_price'))
        week_day_multi = float(request.GET.get('week_day_multi'))
        week_end_multi = float(request.GET.get('week_end_multi'))
        max_discount = float(request.GET.get('max_discount'))
        max_markup = float(request.GET.get('max_markup'))
        coccCategory = request.GET.get('coccCategory')
        aggressiveness = float(request.GET.get('agressiveness'))  # Fix typo if needed
        
        # Regenerate invdf using your existing logic
        # invdf = ... (your code to create the original DataFrame)
        
        # Collect updated advised prices
        advised_prices = {}
        for key in request.POST:
            if key.startswith('advised_price_'):
                date_str = key.split('_')[2]
                try:
                    date = datetime.datetime.strptime(date_str, '%Y-%m-%d').date()
                    price = float(request.POST[key])
                    advised_prices[date] = price
                except (ValueError, IndexError):
                    continue
        
        # Update invdf with new advised prices
        invdf['price_advised'] = invdf['date'].map(advised_prices).fillna(invdf['price_advised'])
        
        # Use invdf as needed
        print(invdf)
        
        return HttpResponse("Data updated successfully!")
    
    # Handle GET request
    else:
        # Your existing code
        # ...

Key Notes:

  • Error Handling: The code includes try-except blocks to handle invalid user input (e.g., non-numeric prices). Adjust this based on your validation needs.
  • Typo Fix: Notice the URL parameter agressiveness (missing an 's'). If this is a mistake, update it to aggressiveness in both the template and view.
  • Security: Since users can edit the hidden inputs via browser dev tools, always validate and sanitize the data in the view before using it.

内容的提问来源于stack exchange,提问作者Barthelemy Lancelot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:38:33