Set ManyToMany field in model save method - django

I have a problem, I try to save the model and only adds to 'members' the users that belong to the company set in the field 'company'.
This is my code:
class GroupFolderAccess(BaseModel):
name = models.CharField(max_length=128)
members = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='belongs')
company = models.ForeignKey('Company', on_delete=models.CASCADE, related_name='folders')
folder = models.ForeignKey('recourse.Folder', null=True, blank=True, on_delete=models.CASCADE, related_name='get_group')
def save(self, *args, **kwargs):
for member in self.members.all():
if self.company != member.company:
print(member)
self.members.remove(member)
return super(GroupFolderAccess, self).save(*args, **kwargs)
When I save, it displays users correctly, but does not remove them from the relationship.

Related

How to show the list paragraphs that belong to the user's Company in the django admin form

I'm developing a project in Django. I have several registered companies, and all models are based on the company.
#models.py
class Company(models.Model):
name = models.CharField(max_length=100)
country = models.CharField(max_length=100)
class XUser(User):
phone = models.CharField(max_length=20, null=True, blank=True)
card = models.CharField(max_length=20, null=False, blank=True)
company = models.ForeignKey(Company, on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return self.nombre
class Book(models.Model):
user = models.ForeignKey(XUser, on_delete=models.CASCADE)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
name = models.CharField(max_length=30)
class Paragraph(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
text = models.CharField(max_length=300)
Now in my admin I define that every user can only see the books of his company.
#admin.py
#admin.register(Book)
class BookAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
# return a filtered queryset
return qs.filter(company=request.user.company)
My question is this: When I try to create a Paragraph instance in the django management form, it shows me all the books and I want it to only show me the ones that belong to the user's Company. Any ideas?
I think you can achieve that by overriding the get_form method to change the queryset of company:
admin.py:
#admin.register(Paragraph)
class ParagraphAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj=None, **kwargs)
form.base_fields['book'].queryset = Book.objects.filter(company=request.user.company)
return form

How to write a business logic involving two models in Django Rest Framework

I am confused and dont know how to write the business logic in django and django rest framework.
How to validate the student that does not already exist in the registration (registration_no will be provided through front end and it will be included in the json) table at the time of student creation?
class Student(models.Model):
name = models.CharField(max_length=300)
sex = models.CharField(choices=SEX_CHOICES,max_length=255, null=True)
Category = models.CharField(max_length=100, null=True)
def __str__(self):
return self.name
RegisrationModel
class Registration(models.Model):
registration_no = models.CharField(max_length=255, unique=True)
student = models.ForeignKey(Student,
on_delete= models.CASCADE, related_name='registrations')
def __str__(self):
return self.registration_no
You can override save() method of model Registration in order to make your verification and raise an exception if there is an student with the same name and registration number already in the database.
class Registration(models.Model):
registration_no = models.CharField(max_length=255, unique=True)
student = models.ForeignKey(Student,
on_delete= models.CASCADE, related_name='registrations')
def __str__(self):
return self.registration_no
def save(self, *args, **kwargs):
try:
Registration.objects.get(student__name=self.name, registration_no=self.registration_no)
except:
super(Registration, self).save(*args, **kwargs)
else:
raise Exception("Student already registered")

How to create an inline formset with manytomany relation in Django

I want to create an inline formset between Preorder model and Product model. The scenario is that the user will be able to select one or more than one products when he decides to create a preorder. On the other hand a product might be found in one or more than one preorders. With that in mind i created a manytomany relationship.
models.py
class Preorder(models.Model):
client = models.ForeignKey(Client,verbose_name=u'Client')
invoice_date = models.DateField("Invoice date",null=True, blank=True, default=datetime.date.today)
preorder_has_products = models.ManyToManyField(Product, blank=True)
def get_absolute_url(self):
return reverse('preorder_edit', kwargs={'pk': self.pk})
class Product(models.Model):
name = models.CharField("Name",max_length=200)
price = models.DecimalField("Price", max_digits=7, decimal_places=2, default=0)
barcode = models.CharField(max_length=16, blank=True, default="")
eopyy = models.CharField("Code eoppy",max_length=10, blank=True, default="")
fpa = models.ForeignKey(FPA, null=True, blank=True, verbose_name=u'Fpa Scale')
forms.py
class PreorderForm(ModelForm):
class Meta:
model = Preorder
exclude = ('client','preorder_has_products',)
def __init__(self, *args, **kwargs):
super(PreorderForm, self).__init__(*args,**kwargs)
self.fields['invoice_date'].widget = MyDateInput(attrs={'class':'date'})
class ProductForm(ModelForm):
#name = ModelChoiceField(required=True,queryset=Product.objects.all(),widget=autocomplete.ModelSelect2(url='name-autocomplete'))
class Meta:
model=Product
fields = '__all__'
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.fields['name'].label="Name"
self.fields['price'].label="Price"
and finally the inline formset:
PreorderProductFormSet = inlineformset_factory(Preorder, Product,
form=ProductForm, extra=1)
After run I face up the issue:ValueError at /
'intranet.Product' has no ForeignKey to 'intranet.Preorder'
Why this happening since I created a manytomany relation?
One solution is to create a foreign key relationship between Preorder and Product model inside Product model..but I do not want to do that since product model is used in other areas of my project and do not want to mess it up.
Any suggestions?

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

Django form objects filter

I want to associate the drop-down lists material and category
models
class Demande_Expertise(models.Model):
user = models.ForeignKey(User)
material = models.ForeignKey("Material")
categorie = models.ForeignKey("Category")
class Category(models.Model):
name = models.CharField(_('name'), max_length=50)
slug = models.SlugField()
expert = models.ForeignKey(Expert, null=True, blank=True, default = None)
class Material(models.Model):
name = models.CharField(_('name'), max_length=50)
description = models.TextField(_('description'), blank=True)
slug = models.SlugField()
category = models.ForeignKey(Category, verbose_name=_('category'))
forms
class Demande_ExpertiseForm(forms.ModelForm):
class Meta:
model = Demande_Expertise
def __init__(self, *args, **kwargs):
super(Demande_ExpertiseForm, self).__init__(*args, **kwargs)
self.fields['material'].queryset = Material.objects.filter(category=Category)
no error but filtering don't work.
how to filter name of the model Category?
You can filter a relation in a queryset by a field by using double underscores (so category__name in this case) and passing in whatever you want to filter it by.
class Demande_ExpertiseForm(forms.ModelForm):
class Meta:
model = Demande_Expertise
def __init__(self, *args, **kwargs):
super(Demande_ExpertiseForm, self).__init__(*args, **kwargs)
self.fields['material'].queryset = Material.objects.filter(category__name="name to filter")
In this case it will filter all of the Material objects to those which have a Category set to exactly name to filter. You can learn more by reading the Django documentation on retrieving objects.