How to work with foreign key with mutiple selection

Viewed 30

Hi Everyone i am trying to achieve select multiple car with foreign key relation because we need to store data with mutiple row, i am tried with manytomany fied but this is not effective as per our requirement, thats way i am trying solve this with foreign key, pls help me out.

models.py

class Car_team(BaseModel):
    team = models.ForeignKey(
        Team,
        models.CASCADE,
        verbose_name='Team',
        null=True,
    )
    car=models.ForeignKey(
        Car, 
        models.CASCADE, 
        verbose_name='Car', 
        null=True)
    city =models.ForeignKey(
        City,
        models.CASCADE,
        verbose_name='City',
    )
    start_date=models.DateField(null=True, blank=True)
    end_date=models.DateField(null=True, blank=True)

forms.py

class CarTeamForm(forms.ModelForm):         
    start_date=forms.DateField(initial=datetime.date.today, label='Start Date')
    car = forms.ModelMultipleChoiceField(queryset=Car.objects.all(), required=True, widget=forms.CheckboxSelectMultiple)
    class Meta:
        model = Car_team
        fields = ['car','team','city','start_date']
    
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(CarTeamForm, self).__init__(*args, **kwargs)
        self.fields['start_date'].widget.attrs['readonly'] = True
        widgets = {
            'car': forms.CheckboxSelectMultiple(attrs={'class': 'form-control select2'}),
        }

views.py

def add_carteam(request, city_id=None, id=None):

    if id is not None:
        carteam = get_object_or_404(Car_team, city_id=city_id, pk=id)
    else:
        carteam = None
    if request.method == 'POST':
        form = CarTeamForm(request.POST, request.FILES,instance=carteam)
        if form.is_valid():
            car = form.cleaned_data['car']
            team = form.cleaned_data['team']
            start_date = Car_team.objects.filter(car__in=car).values_list('start_date', flat=True).filter(end_date__isnull=True)
            # if start_date:
            #     messages.error(request,'Car already assigned to another team!')
            query = Car_team.objects.filter(car__in=car).exists()
            query_set = Car_team.objects.filter(car__in=car).values_list('team', flat=True)
            team_name = Team.objects.filter(pk__in=query_set).values_list('name', flat=True)
            car_id = Car_team.objects.filter(car__in=car).values_list('car', flat=True) 
            car_number=Car.objects.filter(pk__in=car_id).values_list('car_number', flat=True)
            if query_set and start_date:
                messages.error(request,'Car already assigned to team {} {}!'.format(team_name,car_number))
            # if query:
            #     messages.error(request,'Car already assigned to another team!')
            else:
                #print(start_query)
                form.save()
                messages.success(request,'Assign Cars To Teams data added successfully!')
                return redirect('/fleet/carteam_list')
        else:
            messages.error(request,'Please correct the error below.',form.errors)
    else:
        form = CarTeamForm(instance=carteam)
    context = {
        'menu_car_management': 'active',
        'submenu_carteam': 'active',
        'form': form,
        'id': id,
        'city_id': city_id,
    }
    return render(request, 'hiringprocess/addcarteam_form.html', context=context)

addcarteam_form.html

<section class="content">
    <div class="container-fluid">
        <form role="form" method="post" enctype="multipart/form-data" action="/fleet/addcarteam/{{city_id}}/add" autocomplete="off">
            {% csrf_token %}
           
            <div class="row">
                <div class="col-xs-12">
                    <div class="box box-widget"> 
                        <div class="box-body">
                            <div class="col-md-6">
                                {{ form.team|as_crispy_field}}
                            </div>
                            <div class="col-md-6">
                                {{ form.city|as_crispy_field}}
                            </div>
                            <div class="col-md-6">
                                {{ form.start_date|as_crispy_field}}
                            </div>
                            <div class="col-md-12 scroll">
                                {% for i in form.car %}
                                    <div class="col-md-3">
                                        {{i}}
                                    </div>
                                {% endfor %}
                            </div>

                            </div> -->
                        </div>
                    </div>
                </div>
            </div>
            <button type="submit" class="btn btn-primary" style="margin-bottom:20px;">
                <span class="glyphicon glyphicon-ok-circle"></span>
                <span id="btn_txt">Save</span>
            </button>
        </form>
    </div>
</section>

Output Error

ERROR Internal Server Error: /fleet/addcarteam/1/add
Traceback (most recent call last):
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "E:\20_jan_2022_everest\everest_jarvis\fleet\views.py", line 3879, in add_carteam
    if form.is_valid():
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\forms\forms.py", line 185, in is_valid     
    return self.is_bound and not self.errors
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\forms\forms.py", line 180, in errors       
    self.full_clean()
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\forms\forms.py", line 383, in full_clean   
    self._post_clean()
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\forms\models.py", line 398, in _post_clean 
    self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\forms\models.py", line 60, in construct_instance
    f.save_form_data(instance, cleaned_data[f.name])
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\models\fields\__init__.py", line 853, in save_form_data
    setattr(instance, self.name, data)
  File "C:\Users\HI\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\models\fields\related_descriptors.py", line 211, in __set__
    self.field.remote_field.model._meta.object_name,
ValueError: Cannot assign "<QuerySet [<Car: HR38AB6029>, <Car: HR38AB6822>]>": "Car_team.car" must be a "Car" instance.        
ERROR "POST /fleet/addcarteam/1/add HTTP/1.1" 500 114584
1 Answers

You are misunderstanding ForeignKey. CarTeam.car can represent one and only one car, and therefore the CheckboxSelectMultiple widget is inappropriate. Use the default, or maybe RadioSelect.

If you are expecting it to represent multiple cars, it is either ManyToMany, or you have it back to front, and you should have a car_team ForeignKey on the Car model. The set of cars related to a car_team instance is available through that instance as the specified related_name, which defaults to car_set.

You'll need a differerent form to select multiple cars (free ones: queryset Car.objects.filter( car_team__isnull=True ) and then for each, set its car_team to the one you are operating on, and save it.

You can process multiple forms in one view. Use form prefix if any of the field names will clash.

Related