I've multiple models in my Django project but only this given below model creating another instance on update instead of save. This is happening in Django's Admin panel, not on my custom UI. When I remove my save() method then it works fine but this way I won't be able to create slug.
Does anybody know what I'm doing wrong in here
class Course(models.Model):
title = models.CharField(max_length=200)
user = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='category')
slug = models.SlugField(max_length=200, unique=True, primary_key=True, auto_created=False)
short_description = models.TextField(blank=False, max_length=60)
description = models.TextField(blank=False)
outcome = models.CharField(max_length=200)
requirements = models.CharField(max_length=200)
language = models.CharField(max_length=200)
price = models.FloatField(validators=[MinValueValidator(9.99)])
level = models.CharField(max_length=20)
application_link = models.URLField(max_length=1000, blank=True, null=True)
brochure = models.FileField(upload_to='brochures/', blank=True, null=True)
thumbnail = models.ImageField(upload_to='thumbnails/')
video_url = models.CharField(max_length=100)
is_session_available = models.BooleanField(default=False)
session_url = models.CharField(max_length=250, default='')
is_published = models.BooleanField(default=True)
created_at = models.DateTimeField(default=now)
updated_at = models.DateTimeField(default=now)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Course, self).save(*args, **kwargs)
instead of overriding save method you could do this:
admin.py
class CourseAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Course, CourseAdmin)
It is happening because it will generate new slug every time. You can do something like this:
def generate_slug(self):
self.slug = slugify(self.name)
def save(self, *args, **kwargs):
if not self.slug:
self.generate_slug() # This will generate slug.
return super().save(*args, **kwargs)
class Source(models.Model):
Name = models.CharField(max_length=150)`enter code here`
Address = models.CharField(max_length=150)
Office_Phone = PhoneField(blank=True, help_text='Office phone number')
Main_Contact = models.CharField(max_length=150, blank=True, null=True)
Contact_Email = models.EmailField(max_length=254, blank=True, null=True)
Contact_Phone = PhoneField(blank=True, help_text='Main Contact phone number')
Billing_Contact = models.CharField(max_length=150, blank=True, null=True)
Billing_Email = models.EmailField(max_length=254, blank=True, null=True)
Billing_Phone = PhoneField(blank=True, help_text='Billing Contact phone number')
Notes = models.CharField(max_length=250, blank=True, null=True)
def __str__(self):
return self.Name
def get_absolute_url(self):
return reverse('sources-detail', kwargs={'pk': self.pk})
class Rate(models.Model):
Source = models.ForeignKey(Source, on_delete=models.CASCADE)
Report_Type = models.ForeignKey(ReportType, on_delete=models.CASCADE)
Amount = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
class SourceDetailView(DetailView):
model = Source
template_name = 'intake/source_detail.html'
context_object_name = 'source'
def get_context_data(self, *args, **kwargs):
context = super(SourceDetailView, self).get_context_data(*args, **kwargs)
context['rates'] = Rate.objects.all.filter(***not sure what to put here***)
return context
Would it be better to filter it in the Template or do it in the View? I am able to get results if I don't filter it and just use Rate.objects.all(), and then I filter it in my template. Just think there is a better way to do this.
You can just fetch the relation in reverse:
class SourceDetailView(DetailView):
model = Source
template_name = 'intake/source_detail.html'
context_object_name = 'source'
def get_context_data(self, *args, **kwargs):
context = super(SourceDetailView, self).get_context_data(*args, **kwargs)
context['rates'] = self.object.rate_set.all()
return context
That being said, here it does not make much difference to make the query in the template, since there is only one object here, so there is no N+1 problem.
I use Django Restful Api ,I want to post records(more than one record!) in a time ,Models ,serialize,viewset are as follows
Does anyone has some advice? thanks advcance!
model
class Brand(models.Model):
Company_Group = models.ManyToManyField(Company)
Brand_Group = models.CharField(u'Brand Group',max_length=255, default="")
Pref_Brand_Name_Flg = models.CharField(u'Preferred Brand Name Flag',max_length=255, default="")
Pref_Brand_Name = models.CharField(u'Preferred Brand Name',max_length=255, default="")
PrimaryContact = models.ForeignKey(UserRole, null=True, blank=True) #primarybroker
Protect_period = models.CharField(u'Protect period',max_length=255, default="")
# Pref_Brand_Name = models.CharField(u'Preferred Brand Name',max_length=255, default="")
Brand_Name = models.CharField(u'Brand Name',max_length=255, default="")
Brand_Name_SC = models.CharField(u'Brand Name in Local Language',max_length=255, default="")
Year_Enter_Market = models.CharField(u'Entered Market in (Year)',max_length=255, default="")
Category_Display = models.CharField(u'Category Display',max_length=255, default="")
Category_1_Code = models.CharField(u'Category',max_length=255, default="")
Category_2_Code = models.CharField(u'Sub Category',max_length=255, default="")
Price_Low = models.CharField(u'Price Range - Low',max_length=255, default="")
Price_High = models.CharField(u'Price Range - High',max_length=255, default="")
Size_Low = models.CharField(u'Typical Store Size - Low',max_length=255, default="")
Size_High = models.CharField(u'Typical Store Size - High',max_length=255, default="")
Headerquater = models.CharField(u'Headerquater',max_length=255, default="")
Status = models.CharField(u'Status',max_length=255, default="")
Created_On = models.DateField(u'Created On',auto_now_add=True)
Created_By = models.CharField(u'Created By',max_length=255, default="")
Modified_On = models.DateField(u'Modified On', auto_now=True)
Modified_By = models.CharField(u'Modified By',max_length=255, default="")
Agreement_InPlace_Flg = models.CharField(u'TR Agreement in place?',max_length=20, default="")
Web_Site = models.CharField(u'Web Site',max_length=20, default="")
Comment = models.CharField(u'Comment',max_length=20, default="")
viewset
class BrandViewSet(viewsets.ModelViewSet):
queryset = Brand.objects.all()
serializer_class = BrandSerializer
Serializer
class BrandSerializer(serializers.HyperlinkedModelSerializer):
PrimaryContact_id = serializers.ReadOnlyField(source='PrimaryContact.id', read_only=True)
def __init__(self, *args, **kwargs):
many = kwargs.pop('many', True)
super(BrandSerializer, self).__init__(many=many, *args, **kwargs)
class Meta:
model = Brand
fields = data_export_setting.Brand_form_stand # +options ??
#Brand_detail = serializers
"myTest code" :a.py
item = [{"id":"2","PrimaryContact_id":"00000","Pref_Brand_Name_Flg":"00000","Protect_period":"test_for_Protect_period_1","Pref_Brand_Name":"Test","Brand_Name":"Chanel Group","Brand_Name_SC":"test","Year_Enter_Market":"test","Category_Display":"test","Category_1_Code":"api","Category_2_Code":"api","Price_Low":"test","Price_High":"test","Size_High":"test","Headerquater":"test","Status":"test","Created_On":"2017-06-14","Modified_By":"2017-07-08","Modified_On":"000"},{"id":"3","PrimaryContact_id":"1111","Pref_Brand_Name_Flg":"11111","Protect_period":"ppppp","Pref_Brand_Name":"Test","Brand_Name":"Chanel Group 2","Brand_Name_SC":"test","Year_Enter_Market":"test","Category_Display":"test","Category_1_Code":"api","Category_2_Code":"api","Price_Low":"test","Price_High":"test","Size_High":"test","Headerquater":"test","Status":"test","Created_On":"2017-06-14","Modified_By":"2017-07-08","Modified_On":"000"}]
data=json.dumps(item)
def test_get_user_list_3():
resp = requests.post(urlname,auth=AUTH,data=data,headers={ "Content-Type":"application/json","Accept": "application/json"})
test_get_user_list_3()
if item as for one record ,it works
item ={"id":"1","PrimaryContact_id":"00000","Pref_Brand_Name_Flg":"00000","Protect_period":"test_for_Protect_period_1","Pref_Brand_Name":"Test","Brand_Name":"Chanel Group","Brand_Name_SC":"test","Year_Enter_Market":"test","Category_Display":"test","Category_1_Code":"api","Category_2_Code":"api","Price_Low":"test","Price_High":"test","Size_High":"test",Headerquater":"test","Status":"test","Created_On":"2017-06-14","Modified_By":"2017-07-08","Modified_On":"000"},
Ok, i've spent a considerable amount of time trying to get this work. Below is the code that i've used to get this to do bulk creates.
The get_serializer method that's used by default for ModelViewSet passes in the data without many=True so you have to override it and make sure you check the request for a list instead of a dictionary.
That's the only change required to be able to bulk create items from a list.
models.py
class Brand(models.Model):
# ------------------------------------------
# Relations
# ------------------------------------------
Company_Group = models.ManyToManyField(Company)
PrimaryContact = models.ForeignKey(User, null=True, blank=True)
# ------------------------------------------
# Attributes
# ------------------------------------------
# Brand attrs
Brand_Name = models.CharField(u'Brand Name',max_length=255, blank=True)
Brand_Group = models.CharField(u'Brand Group',max_length=255, blank=True)
Pref_Brand_Name = models.CharField(u'Preferred Brand Name',max_length=255, blank=True)
Brand_Name_SC = models.CharField(u'Brand Name in Local Language',max_length=255, blank=True)
Pref_Brand_Name_Flg = models.CharField(u'Preferred Brand Name Flag',max_length=255, blank=True)
# Record management attrs
Modified_On = models.DateField(u'Modified On', auto_now=True)
Created_On = models.DateField(u'Created On', auto_now_add=True)
Created_By = models.CharField(u'Created By', max_length=255, blank=True)
Modified_By = models.CharField(u'Modified By', max_length=255, blank=True)
# Category attrs
Category_1_Code = models.CharField(u'Category', max_length=255, blank=True)
Category_2_Code = models.CharField(u'Sub Category', max_length=255, blank=True)
Category_Display = models.CharField(u'Category Display',max_length=255, blank=True)
# Pricing attrs
Price_Low = models.CharField(u'Price Range - Low', max_length=255, blank=True)
Price_High = models.CharField(u'Price Range - High', max_length=255, blank=True)
# Store attrs
Size_Low = models.CharField(u'Typical Store Size - Low', max_length=255, blank=True)
Size_High = models.CharField(u'Typical Store Size - High', max_length=255, blank=True)
# Company attrs
Status = models.CharField(u'Status', max_length=255, blank=True)
Comment = models.CharField(u'Comment', max_length=20, blank=True)
Web_Site = models.CharField(u'Web Site', max_length=20, blank=True)
Headerquater = models.CharField(u'Headerquater', max_length=255, blank=True)
Protect_period = models.CharField(u'Protect period', max_length=255, blank=True)
Year_Enter_Market = models.CharField(u'Entered Market in (Year)', max_length=255, blank=True)
Agreement_InPlace_Flg = models.CharField(u'TR Agreement in place?', max_length=20, blank=True)
def __str__(self):
return self.Brand_Name
class Meta:
db_table = 'brand'
serializers.py
class BrandSerializer(serializers.ModelSerializer):
class Meta:
model = Brand
fields = '__all__'
views.py
class BrandViewSet(viewsets.ModelViewSet):
model = Brand
serializer_class = BrandSerializer
queryset = Brand.objects.all()
def get_serializer(self, *args, **kwargs):
if 'data' in kwargs:
data = kwargs['data']
if isinstance(data, list):
kwargs['many'] = True
return super().get_serializer(*args, **kwargs)
urls.py
from rest_framework.routers import DefaultRouter
from .views import BrandViewSet
router = DefaultRouter()
router.register(r'brand', BrandViewSet)
urlpatterns = router.urls
I sent the data(JSON) using postman in this format:
[
{
"Brand_Name":"",
"Brand_Group":"",
"Pref_Brand_Name":"",
"Brand_Name_SC":"",
"Pref_Brand_Name_Flg":"",
"Created_By":"",
"Modified_By":"",
"Category_1_Code":"",
"Category_2_Code":"",
"Category_Display":"",
"Price_Low":"",
"Price_High":"",
"Size_Low":"",
"Size_High":"",
"Status":"",
"Comment":"",
"Web_Site":"",
"Headerquater":"",
"Protect_period":"",
"Year_Enter_Market":"",
"Agreement_InPlace_Flg":"",
"PrimaryContact":null,
"Company_Group":[
1
]
},
{
"Brand_Name":"",
"Brand_Group":"",
"Pref_Brand_Name":"",
"Brand_Name_SC":"",
"Pref_Brand_Name_Flg":"",
"Created_By":"",
"Modified_By":"",
"Category_1_Code":"",
"Category_2_Code":"",
"Category_Display":"",
"Price_Low":"",
"Price_High":"",
"Size_Low":"",
"Size_High":"",
"Status":"",
"Comment":"",
"Web_Site":"",
"Headerquater":"",
"Protect_period":"",
"Year_Enter_Market":"",
"Agreement_InPlace_Flg":"",
"PrimaryContact":null,
"Company_Group":[
1
]
}
]
As shown in DRF documentation you can utilize the ListSerializer to create multiple instances of the model.
Your best bet is to create a separate serializer(ListSerializer) with an your own custom .create() method for creating multiple instances of your model. Then in your view you write some business logic to check if it's a single object or a list of multiple objects and send them to the appropriate serializer for creation. Make sure you take a look at the ListSerializer and how to use many=True.
You can potentially use the same serializer with your own custom .create() method and have the business logic inside of there but look at the documentation and see the recommended way of creating multiple instances of objects.
i want to filter the many to many field in modelform.
class IdealBehaviour(models.Model):
cbs_role = models.ManyToManyField(CbsRole, null=True, blank=True)
cbs = models.ForeignKey('cbs.CBS', null=True, blank=True)
ideal_behaviour = models.CharField(max_length=500, null=True, blank=True)
Description = models.CharField(max_length=1000, null=True, blank=True)
created_time = models.DateTimeField(auto_now_add = True,null=True, blank=True)
class StandardWork(models.Model):
cbs_and_role = models.ManyToManyField('userdata.CbsRole', null=True, blank=True)
standard_work_number = models.BigIntegerField(null=True, blank=True)
system_name= models.CharField(max_length=500, null=True, blank=True)
system_description=models.TextField(null=True, blank=True)
ideal_behaviour = models.ManyToManyField ('userdata.IdealBehaviour', null=True, blank=True)
publish = models.BooleanField(default=False)
created_time = models.DateTimeField(auto_now_add = True,null=True, blank=True)
class TodoListForm(ModelForm): # used in manage view
class Meta:
model = StandardWork
exclude = ('publish', 'cbs_and_role', 'standard_work_number')
widgets = {
'system_description': forms.Textarea(attrs={'rows':3}),
}
i want to display the choices of ideal_behaviour for the query
cbsobject = CBS.objects.get(id=dat)
idealbehaviour = IdealBehaviour.objects.filter(cbs=cbsobject)
I want to choices for ideal_behaviour in TodoListForm as idealbehaviour only.
How can i query to display ideal-behaviour assosciated with that perticuler cbs only in modelform?
i got the solution
def __init__(self, *args, **kwargs):
super(PollForm, self).__init__(*args, **kwargs)
if self.instance:
print "printing in form"
print self.instance.id
self.fields['ideal_behaviour'].queryset = IdealBehaviour.objects.filter(cbs__exact=self.instance.id)
but i dont how to get the id for cbs. self.instance.id its giving for standardwork id. i want id for cbs. i.e cbsobject i want in form as a instance. after that its working fine.
Got the solution.
I don't know if it is feasible or not, but I put the forms in the views file only so I can get the instance for "cbsobject".
class PollForm(forms.ModelForm): # used in manage view
class Meta:
model = StandardWork
exclude = ('cbs_and_role','publish', 'standard_work_number')
widgets = {
'system_description': forms.Textarea(attrs={'rows':3}),
}
def __init__(self, *args, **kwargs):
super(PollForm, self).__init__(*args, **kwargs)
if self.instance:
print "printing in form"
print self.instance.id
self.fields['ideal_behaviour'].queryset = IdealBehaviour.objects.filter(cbs__exact=cbsobject)