Select a valid choice ModelMultipleChoiceField error - django

I'm trying to make form that allows to user selecting employers by the checkbox list, depends on their team using ModelMultipleChoiseField. I can filter proper employers per team but when i select any of then i had error
Select a valid choice. 3 is not one of the available choices.
And i don't know what is wrong ;/
This is my form class :
class TaskDictForm(forms.Form):
team_id = 0
order = forms.IntegerField(min_value=0)
name = forms.CharField(max_length=200)
start = forms.DateTimeField()
previous = forms.CharField(max_length=200)
employers = forms.ModelMultipleChoiceField(queryset=None, widget=forms.CheckboxSelectMultiple)
def __init__(self, *args, **kwargs):
initial = kwargs.get('initial', {})
if hasattr(self, 'initial_values') and not kwargs.get('data'):
for field_name, value in self.initial_values.items():
if not getattr(kwargs.get('instance', None), field_name, None):
initial[field_name] = value
kwargs.update({'initial': initial})
if hasattr(self, 'required_fields'):
for field_name in self.required_fields:
self.fields[field_name].required = True
tmp = kwargs.pop('pk', None)
self.team_id = tmp
super(TaskDictForm, self).__init__(*args, **kwargs)
self.fields['employers'].queryset = Employer.objects.filter(team=self.team_id)
Employer and Team models:
class Team(models.Model):
name = models.CharField(default='Team', max_length=100, unique=True)
def __str__(self):
return self.name
class Employer(models.Model):
user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
team = models.ForeignKey(Team, on_delete=models.SET_NULL, null=True)
team_leader = models.BooleanField(default=False)
project_menager = models.BooleanField(default=False)
# project_id = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True)
hourly_rate = models.IntegerField(default=0)
working_time = models.FloatField(default=0.0)
def __str__(self):
return (self.user.first_name + ' ' + self.user.last_name)
The same proble is when i try use MultipleChoiseField

Related

How to filter in Django Rest Framework function based view?

So many documentation for filtering in Django rest framework but all the examples are in class based view. but I am trying to do the same in DRF function based view. I wanted to do multiple filter for my items queryset.
I tried one way and it is working perfectly. Here first I am trying to search by item name or restaurant name in one request. then I take another keyword and try to filter restaurant name or item name based on restaurant city. It is working perfectly like if I hit this url
http://localhost:8000/api/items/?keyword=lasagne&keyword1=paris
then it gives me the perfect response.
But What I am asking for is that now my code looks for this specific part is messy and I want to add more fields for multiple filtering. Which procedure to follow? Should I follow this one and multiple requests and trying to filter from this.
Suppose now I want to filter the queryset based on dish_type, price, item_type, location and then search for items by name or restaurants by name
#this is my models
class Restaurant(models.Model):
user = models.OneToOneField(CustomUser, related_name='restaurant', on_delete=models.CASCADE, null=False)
name = models.CharField(max_length=200, blank=True, null=True)
profile_picture = models.ImageField(null=True, blank=True)
address = models.TextField(max_length=2000, blank=True, null=True)
city = models.CharField(max_length=200)
latitude = models.DecimalField(max_digits = 13, decimal_places = 7, blank=True, null=True)
longitude = models.DecimalField(max_digits = 13, decimal_places = 7, blank=True, null=True)
is_verified = models.BooleanField(default=False)
createdAt = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.name)
class Item(models.Model):
user = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
name = models.CharField(max_length=220)
image = models.ImageField(null=True, blank=True)
dish_type = models.ForeignKey(Dishtype, on_delete=models.CASCADE)
item_type = models.ForeignKey(Itemtype, on_delete=models.CASCADE)
description = models.TextField(max_length=10000)
rating = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)
numReviews = models.IntegerField(null=True, blank=True, default=0)
old_price = models.DecimalField(max_digits=11, decimal_places=2)
discount = models.IntegerField(blank=True, null=True)
price = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True)
countInStock = models.IntegerField(blank=True, null=True, default=0)
createdAt = models.DateTimeField(auto_now_add=True)
_id = models.AutoField(primary_key=True, editable=False)
def save(self, *args, **kwargs):
self.price = Decimal(self.old_price * (100 - self.discount) / 100)
return super(Item, self).save(*args, **kwargs)
class Meta:
ordering = ['-createdAt']
def __str__(self):
return self.name
#serializer
class RestaurantSerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Restaurant
fields = '__all__'
def get_user(self, obj):
user = obj.user
serializer = UserSerializer(user, many=False)
return serializer.data
class ItemSerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField(read_only=True)
dish_type = serializers.SerializerMethodField(read_only=True)
item_type = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Item
fields = '__all__'
def get_user(self, obj):
user = obj.user
serializer = RestaurantSerializer(user, many=False)
return serializer.data
def get_dish_type(self, obj):
dish_type = obj.dish_type
serializer = DishtypeSerializer(dish_type, many=False)
return serializer.data
def get_item_type(self, obj):
item_type = obj.item_type
serializer = ItemtypeSerializer(item_type, many=False)
return serializer.data
#views.py
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def getItems(request):
user = request.user
query = request.query_params.get('keyword')
if query == None:
query = ''
cuery = request.query_params.get('keyword1')
if cuery == None:
cuery = ''
items = Item.objects.select_related('user').select_related('dish_type').select_related('item_type').all().filter(
Q(name__icontains = query) | Q(user__name__icontains = query))
else:
restaurant_city = Item.objects.select_related('user').select_related('dish_type').select_related('item_type').all(
).filter(Q(user__city__iexact = cuery))
items = restaurant_city.filter(Q(name__icontains = query) | Q(user__name__icontains = query))
serializer = ItemSerializer(items, many=True)
return Response(serializer.data)
######Updated solved the problem
#filters.py
class ItemFilter(django_filters.FilterSet):
numReviews = django_filters.NumberFilter()
numReviews__gt = django_filters.NumberFilter(field_name='numReviews', lookup_expr='gt')
numReviews__lt = django_filters.NumberFilter(field_name='numReviews', lookup_expr='lt')
name = django_filters.CharFilter(lookup_expr='icontains')
class Meta:
model = Item
fields = ['_id', 'dish_type__id']
#views
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def getItems(request):
user = request.user
queryset = Item.objects.all()
filterset = ItemFilter(request.GET, queryset=queryset)
if filterset.is_valid():
queryset = filterset.qs
serializer = ItemSerializer(queryset, many=True)
return Response(serializer.data)
now data are passing like this
http://localhost:8000/api/items/?numReviews__gt=20&numReviews__lt=22
You can use queryset and override get_queryset function.
class FooViewSet(GenericViewSet, mixins.ListModelMixin):
authentication_classes = [JSONWebTokenAuthentication]
permission_classes = [IsAuthenticated]
serializer_class = ItemSerializer
def get_queryset(self):
query = self.request.query_params.get('keyword', '')
if not self.request.query_params.get('keyword1'):
items = Item.objects.select_related('user').select_related('dish_type').select_related(
'item_type').all().filter(
Q(name__icontains=query) | Q(user__name__icontains=query))
else:
restaurant_city = Item.objects.select_related('user').select_related('dish_type').select_related(
'item_type').all(
).filter(Q(user__city__iexact=self.request.query_params.get('keyword1', '')))
items = restaurant_city.filter(Q(name__icontains=query) | Q(user__name__icontains=query))
return items

Django - Form - ForeignKey - Hidden - Default value

I have a Hidden ForeignKey in an update form that I want to set to value of default value of 2 in my html form, but I can't get it to work.
forms.py
eval_sent_state = forms.ModelChoiceField(widget=forms.HiddenInput(), initial=2,queryset=models.EvalUrlSentState.objects.all())
The Html output i get:
<input type="hidden" name="eval_sent_state" value="1" id="id_eval_sent_state">
from views.py
class ClassSchoolTeacherUpdateView(generic.UpdateView):
model = models.ClassSchool
form_class = forms.ClassSchoolTeacherForm
pk_url_kwarg = "pk"
def get_object(self, queryset=None):
return models.ClassSchool.objects.get(class_random_key=self.kwargs.get("random"))
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['username'] = self.kwargs.get('username')
context['random'] = self.kwargs.get('random')
return context
from models.py:
class ClassSchool(models.Model):
# Relationships
eval_sent_state = models.ForeignKey("EvalUrlSentState", default=1, on_delete=models.SET_NULL, blank=True, null=True)
# Fields
class_name = models.CharField(max_length=100)
class_student_size = models.IntegerField(blank=True, null=True)
class_subject = models.CharField(max_length=100)
class_element_name = models.CharField(max_length=100)
class_teacher_user = models.CharField(max_length=100)
class_teacher_name = models.CharField(max_length=100, blank=True, null=True)
eval_year = models.IntegerField(default=2022)
class_random_key = models.CharField(max_length=8)
eval_url = models.CharField(max_length=400)
eval_open_datetime = models.DateTimeField(null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
You can override your form to always set the eval_sent_state field to the value you want in the save method, you should remove the field from the form fields though
class ClassSchoolTeacherForm(forms.ModelForm):
class Meta:
model = ClassSchool
exclude = ['eval_sent_state']
def save(self, *args, **kwargs):
self.instance.eval_sent_state_id = 2
return super().save(*args, **kwargs)

How to create slug of many to many fields in django?

I want to make slugs on post save for my model using three fields one charfield and two ManytoMany Fields but getting error during saving.
Here is my code:
Heading ##class product(models.Model):
id = models.AutoField(primary_key=True)
image = models.ForeignKey(all_images, verbose_name='Product Images', on_delete=models.CASCADE, related_name='proimages')
ProductName = models.CharField(max_length=200, null=False,default="None", blank=False,verbose_name="Product Name")
CategoryName = models.ManyToManyField(category,related_name='procat', blank=False,verbose_name="Category Name")
SubcatName = models.ManyToManyField(subcategory,related_name='prosubcat', blank=False,verbose_name="Sub-category Name")
description = RichTextUploadingField(blank= False,verbose_name="Description")
price = models.IntegerField(default=100, null=True, blank=True, verbose_name='Price')
slug = models.SlugField(max_length=55, blank=True, null=True)
def get_slug(self):
slug = self.ProductName
try:
for items in self.SubcatName.all():
slug +=items.name
try:
for items in self.CategoryName.all():
slug +=items.CategoryName
except:
pass
except:
pass
return slugify(slug)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = self.get_slug()
super(product, self).save(*args, **kwargs)

How can i get a object from a other function in django

I have two functions projectTimerStart to start the timer and projectTimerStop
i want to use the object which is created in projectTimerStart and i want to end the time when projectTimerStop , and this should be saved in a database
ps: Both the functions are not in class they are normal functions
def projectTimerStart(request, slug):
project_detail = Project.objects.get(slug=slug)
b = ProjectTimer(time_started=datetime.now(),
working_project=project_detail,
working_freelancer=request.user
)
b.save()
return HttpResponseRedirect(reverse('project_timer', kwargs=
{"slug":slug}))
def projectTimerStop(request, slug):
project_detail = Project.objects.get(slug=slug)
#i want something here super method or something
return HttpResponseRedirect(reverse('project_timer', kwargs=
{"slug": slug}))
models.py
class Project(models.Model):
project_title = models.CharField(max_length=100)
project_description = models.TextField()
created_by = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='created')
assigned_to = models.ManyToManyField(
User, blank=True, related_name='assigned_by')
slug = models.SlugField()
hourly_budget = models.PositiveIntegerField(blank=True, null=True)
technologies = models.ManyToManyField(
Technologies, related_name='technologies_used')
time_posted = models.DateTimeField(auto_now_add=True)
request_id = models.ManyToManyField(
User, related_name='requested_by', blank=True)
def __str__(self):
return self.project_title
def save(self, *args, **kwargs):
self.slug = slugify(self.project_title)
super(Project, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('project_detail', kwargs={'slug': self.slug})
def get_timer_url(self):
return reverse('project_timer', kwargs={'slug': self.slug})
def round_datetime(dt):
minutes = round((dt.minute + float(dt.second) / 60) / 15) * 15 -
dt.minute
return dt + datetime.timedelta(minutes=minutes, seconds=-dt.second)
class ProjectTimer(models.Model):
time_started = models.DateTimeField()
time_ended = models.DateTimeField(blank=True, null=True)
working_project = models.ForeignKey(Project, on_delete=models.CASCADE)
working_freelancer = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True)
If each of your project objects will have one and only project timer objects, you can add project_timer = models.OneToOneField(ProjectTimer) to your Project model and access to the project timer by using project_detail.project_timer.
If not, you need to know at least one feature of that project_timer in order to fetch it from database. Or you can iterate all of your ProjectTimer objects that belongs to that Project and select the appropriate one by:
models.py
class Project(models.Model):
# Some fields
project_timers = models.ManyToManyField(ProjectTimer)
views.py
def projectTimerStop(request, slug):
project_detail = Project.objects.get(slug=slug)
for pt in project_detail.project_timers.all():
if pt.some_field == "THIS IS CORRECT TIMER":
# Here is your project_detail
print(str(pt))
return HttpResponseRedirect(reverse('project_timer', kwargs=
{"slug": slug}))

How to create an inline formset for a reverse foreign key relationship

I have a Property Model as follows =
class Property(models.Model):
property_type = models.CharField(max_length=255, default='Apartment')
specifications = models.CharField(max_length=255, default='Basic')
built_up_area = models.FloatField(max_length=6, null=False, default=0)
total_area = models.FloatField(null=False, default=0)
number_of_bedrooms = models.CharField(max_length=3, default=1)
number_of_bathrooms = models.CharField(max_length=3, default=1)
number_of_parking_spaces = models.CharField(max_length=2, default=0)
address_line_one = models.CharField(max_length=255, null=False)
address_line_two = models.CharField(max_length=255, null=True, default=None)
connectivity = models.CharField(max_length=255, default=None, null=True)
neighborhood_quality = models.CharField(max_length=255, default=None,
null=True)
comments = models.CharField(max_length=255, default=None, null=True)
city = models.ForeignKey('City')
state = models.ForeignKey('State')
pin_code = models.ForeignKey('PinCode')
developer = models.ForeignKey('Developer', null=True, default=None)
owner = models.ForeignKey('Owner', null=True, default=None)
created_by = models.ForeignKey('custom_user.User')
project = models.ForeignKey('Project')
def __unicode__(self):
return self.property_type
class Meta:
verbose_name_plural = 'Properties'
And a City model as follows -
class City(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(City, self).save(*args, **kwargs)
def __unicode__(self):
return self.name
Now I want to make a single form where I can enter the Property details and while entering the city, I can enter the name of the city instead of selecting from the dropdown list.
So how do I create the inline formset using the inlineformset_factory to create the form?
==EDIT==
I've tried to use the following code to create the formset
CityFormset = inlineformset_factory(City, Property,
fields=('city',),
extra=0,
min_num=1,
can_delete=False)
You've misunderstood what an inline formset is. It's for editing the "many" side of a one-to-many relationship: that is, given a parent model of City, you could edit inline the various Properties that belong to that city.
You don't want a formset at all to simply edit the single City that a property can belong to. Instead, override the city field within your Property form to be a TextField, and either create a new City or find an existing one in the clean_city method.
class PropertyForm(forms.ModelForm):
city = forms.TextField(required=True)
class Meta:
model = Property
exclude = ('city',)
def __init__(self, *args, **kwargs):
super(PropertyForm, self).__init__(*args, **kwargs)
if self.instance and not self.data:
self.initial['city'] = self.instance.city.name
def save(self, commit=True):
city_name = self.cleaned_data['city']
city, _ = City.objects.get_or_create(name=city_name)
instance = self.save(commit=False)
instance.city = city
if commit = True:
instance.save()
return instance