I am trying to serialize software model with its related image fields. Images are refered to Software model with foreign key and when i serialize the software model i want it to return the images or image paths as well. I cannot make a image field on Software model since multiple images will be relating to it. How would i serialize a model and its related models that are refered by a foreign key?
class Software(models.Model):
"""
Base model for listings
"""
SOFTWARE_TYPE = (
('R', 'Retail'),
('H', 'Hospitality'),
)
objects = SoftwareManager()
slug = models.SlugField(unique=True,blank=True, null=True)
submitted_by = models.ManyToManyField(User, blank=True, null=True)
title = models.CharField(max_length=120, blank=True, null=True)
developer = models.CharField(max_length=120, blank=True, null=True)
address = models.CharField(max_length=120, blank=True, null=True)
city = models.CharField(max_length=60, blank=True, null=True)
state = models.CharField(max_length=60, blank=True, null=True)
zipcode = models.CharField(max_length=5, blank=True, null=True)
description = models.TextField(blank=True, null=True)
objects = models.GeoManager()
rating = RatingField(range=5,weight=5,can_change_vote=True)
business_size = models.ManyToManyField("BusinessSize", related_name="software-business-size")
review = generic.GenericRelation("Review")
def __unicode__(self):
#return "%s %s %s"%(self.title, self.point.x, self.point.y)
return "%s"%(self.title)
#models.permalink
def get_absolute_url(self):
return ('software-detail', (),
{
'slug' :self.slug,
})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Software, self).save(*args, **kwargs)
def natural_key(self):
return (self.title, self.developer)
class Meta:
unique_together = (('title', 'developer'),)
class SoftwareImage(models.Model):
software = models.ForeignKey(Software, related_name="softwareimages")
image = models.ImageField(upload_to='software/%Y/%m/%d', default='static/img/no-thumb.jpg', null=True, blank=True)
Views.py
def software_list_ajax_all(request):
result = Software.objects.all().select_related()
result = serializers.serialize('json', result, relations=('software',), extras=('__unicode__','get_absolute_url') )
return HttpResponse(result, content_type="application/json")
Json Response
1: Object
extras: Object
__unicode__: "test "
get_absolute_url: "/software/test/"
__proto__: Object
fields: Object
address: "test "
business_size: Array[1]
city: "test"
description: ""
developer: "test"
rating_score: 0
rating_votes: 0
slug: "test"
state: "CA "
submitted_by: Array[0]
title: "Comcash "
zipcode: "test"
__proto__: Object
model: "softwareapp.software"
pk: 3
Here is the solution. Basically I ended up using Django Rest framework. Custom relational fields feature of DRF enables you to create serializer relations.
class SoftwareImageField(serializers.RelatedField):
def to_native(self, value):
return '%s' % (value.image.url)
class SoftwareSerializer(serializers.HyperlinkedModelSerializer):
absurl = serializers.Field(source='get_absolute_url')
softwareimages = SoftwareImageField(many=True)
class Meta:
model = Software
fields = ('url','title','developer','absurl','slug','softwareimages')
Views.py
def software_list_ajax_all(request):
result = Software.objects.all()
serializer = SoftwareSerializer(result)
return JSONResponse(serializer.data)
Related
I am getting Issue while edit a record based on CHatquestion ID, if option is null then i need to add a record based on same chatquestion id, if chatqustion id exist in option it will work,
i am trying to multiple way to solve this issue but still can't find solution.
Models.py # thease are all 3 models
class Problem(models.Model):
Language = models.IntegerField(choices=Language_CHOICE, default=1)
type = models.CharField(max_length=500, null=True, blank=True)
def __str__(self):
return self.type
class ChatQuestion(models.Model): # Eding record based on chatquestion id
question = RichTextField(null=True, blank=True)
problem_id = models.ForeignKey(
Problem,
models.CASCADE,
verbose_name='Problem',
)
def __str__(self):
return self.question
is_first_question = models.BooleanField(default=False)
class Option(models.Model):
option_type = models.CharField(max_length=250, null=True, blank=True)
question_id = models.ForeignKey(
ChatQuestion,
models.CASCADE,
verbose_name='Question',
null=True,
blank=True
)
problem=models.ForeignKey(
Problem,
models.CASCADE,
verbose_name='Problem',
null=True,
blank=True
)
next_question_id = models.ForeignKey(ChatQuestion, on_delete=models.CASCADE, null=True, blank=True,
related_name='next_question')
def __str__(self):
return self.option_type
forms.py
class EditQuestionForm(forms.ModelForm):
class Meta:
model = ChatQuestion
fields =('question','problem_id')
class EditOptionForm(forms.ModelForm):
class Meta:
model = Option
fields =('option_type',)
views.py
def question_edit(request,id=None):
if id is not None:
queryset = get_object_or_404(ChatQuestion,pk=id)
queryset1=get_object_or_404(Option,question_id=queryset )
else:
queryset = None
queryset1 = None
if request.method=="POST":
form = EditQuestionForm(request.POST ,instance=queryset)
form1=EditOptionForm(request.POST, instance=queryset1)
if form.is_valid() and form1.is_valid():
question=form.cleaned_data['question']
option_type=form1.cleaned_data['option_type']
if id:
queryset.question=question
queryset.save()
queryset1.option_type=option_type
queryset1.save()
messages.success(request,'Sucessful')
return redirect('/fleet/list_chatbot')
else:
print(form.errors)
messages.error(request,'Please correct following',form.errors)
elif id:
form = EditQuestionForm(instance=queryset)
form1=EditOptionForm(instance=queryset1)
if not queryset1:
form1=EditOptionForm()
else:
form = EditQuestionForm()
form1=EditOptionForm()
context={
'form':form,
'form1':form1
}
return render(request,'chatbot/question_edit.html',context=context)
I have a model form that creates a new job entry, and on submission, I need an invisible field job_time_estimation to be set to a sum of 'service_stats_estimate_duration' values from ServiceItemStats objects associated with the JobEntry by a many-to-many relationship when submitting the form.
For example, if in my NewJobEntryForm I chose two existing ServiceItemStats objects that have service_stats_estimate_duration values 60 and 90, on submission, I want a value 150 to be saved in that JobEntry object's job_time_estimation attribute.
I tried doing this using aggregation by defining a save() method in the model but I am getting an error "name 'serviceItemStats' is not defined".
I am not sure if I am going about this the right way. Any help would be appreciated.
My code:
models.py:
class ServiceItemStats(models.Model):
service_stats_name = models.CharField(primary_key=True, max_length=20)
service_stats_estimate_duration = models.IntegerField()
# Many-to-many relationship with JobEntry.
def __str__(self):
return self.service_stats_name
class JobEntry(models.Model):
# PK: id - automatically assigned by Django.
jo
b_entry_date_time = models.DateTimeField(default=timezone.now)
jo
b_date = models.DateField(blank=True, null=True)
job_checked_in = models.BooleanField()
job_checked_out = models.BooleanField(default=False)
job_priority = models.IntegerField()
job_time_estimation = models.IntegerField(blank=True, null=True)
job_comments = models.TextField(max_length=200, blank=True, null=True)
job_parts_instock = models.BooleanField(default=False)
job_started = models.BooleanField(default=False)
job_finished = models.BooleanField(default=False)
job_expand_fault_evidence = models.ImageField(blank=True, null=True)
job_expand_comments = models.ImageField(blank=True, null=True)
job_expand_parts_required = models.CharField(max_length=200, blank=True, null=True)
vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE) #One-to-one relationship
customer = models.ForeignKey(Customer, on_delete=models.CASCADE) #One-to-one relationship
serviceBay = models.ForeignKey(ServiceBay, on_delete=models.CASCADE, blank=True, null=True) #One-to-one relationship
serviceItemStats = models.ManyToManyField(ServiceItemStats, blank=True) #Many-to-many relationship
def __str__(self):
return self.id
def save(self, *args, **kwargs):
if not self.job_time_estimation:
self.job_time_estimation = serviceItemStats.objects.all().aggregate('service_stats_estimate_duration')
return super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse("jobs:job_detail",kwargs={'pk':self.pk})
views.py
class JobCreateView(FormView):
template_name = "jobs/jobentry_form.html"
form_class = NewJobEntryForm
success_url = reverse_lazy("jobs:job_list")
def form_valid(self, form):
form.save()
return super(job_list, self).form_valid(form)
forms.py
class NewJobEntryForm(ModelForm):
class Meta:
model = JobEntry
fields = ['vehicle', 'customer', 'job_date', 'job_checked_in', 'job_priority', 'job_comments', 'job_parts_instock', 'serviceItemStats']
widgets = {
'job_date' : forms.DateInput(format=('%m/%d/%Y'), attrs={'class':'form-control', 'placeholder':'Select a date', 'type':'date'}),
'ServiceItemStats' : forms.CheckboxSelectMultiple(),
'job_priority' : forms.RadioSelect(choices=priorityOptions),
}
You can try this.
from django.db.models import Sum
class JobCreateView(FormView):
template_name = "jobs/jobentry_form.html"
form_class = NewJobEntryForm
success_url = reverse_lazy("jobs:job_list")
def form_valid(self, form):
job=form.save()
estimation = job.serviceItemStats.all().aggregate(total=Sum('service_stats_estimate_duration'))
job.job_time_estimation = estimation['total']
job.save()
return super(job_list, self).form_valid(form)
django masters all around the world
I'm Korean developer and started django 3 months ago.
Now I'm just a slave of my company.
Anyway, I have problem on optimizing django admin project, but no one has experienced the same problem.
This is my models "Project", "Answer", "Request".
# ------------------------------------------------------------------
# Model : Project
# Description : project model
# ------------------------------------------------------------------
class Project(models.Model):
class Meta:
verbose_name = ' project'
verbose_name_plural = ' project'
def __str__(self):
return str(self.id)
# ------------------------------------------------------------------
# Model : Request
# Description : Request model
# ------------------------------------------------------------------
class Request(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE, verbose_name='client')
project = models.ForeignKey(Project, on_delete=models.CASCADE, verbose_name='project')
product = models.ForeignKey(Subclass, on_delete=models.CASCADE, verbose_name='product')
category = models.ManyToManyField(Develop, verbose_name='category')
name = models.CharField('name', max_length=256, blank=True, null=True)
price = models.CharField('price', max_length=256, blank=True, null=True)
day = models.CharField('duedate', max_length=256, blank=True, null=True)
content = RichTextUploadingField('content', null=True)
file = models.FileField('file', upload_to=request_update_filename, blank=True, null=True)
created_at = models.DateTimeField('created_at', default=time)
add_meeting = models.BooleanField('add_meeting', default=False, null=True)
examine = models.BooleanField('check examing', default=False, null=True)
active_save = models.BooleanField('active-save', default=True, null=True)
class Meta:
verbose_name = ' request'
verbose_name_plural = ' requests'
def __str__(self):
return str(self.name)
class Answer(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE, verbose_name="client")
project = models.ForeignKey(Project, on_delete=models.CASCADE, verbose_name="project", null=True)
partner = models.ForeignKey(Partner, on_delete=models.CASCADE, verbose_name="partner")
class Meta:
verbose_name = ' Answer'
verbose_name_plural = ' Answer'
def __str__(self):
return str(self.id)
and this is my admin code
#admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
inlines = [RequestInline,AnswerInline]
list_display = ['request_name','client_email','project_price','project_created','count_answer','count_meeting','answer_status']
def request_name(self, obj):
project_id = obj.id
request_name = Request.objects.get(project = project_id)
return request_name
def client_email(self, obj):
project_id = obj.id
client = Request.objects.get(project=project_id).client
return client
def client_phone(self, obj):
project_id = obj.id
client = Request.objects.get(project=project_id).client
phone = User.objects.get(username=client).phone
return phone
def project_price(self, obj):
project_id = obj.id
request_price = Request.objects.get(project=project_id).price
return request_price
def project_created(self, obj):
project_id = obj.id
created_at = Request.objects.get(project=project_id).created_at
return created_at
def count_answer(self, obj):
project_id = obj.id
answer_qs = Answer.objects.all()
answer = Answer.objects.filter(project=project_id)
count = len(answer)
return count
def count_meeting(self, obj):
project_id = obj.id
answer_yes = Answer.objects.filter(project = project_id, state = 1)
count = len(answer_yes)
return count
def answer_status(self, obj):
project_id = obj.id
answer = Answer.objects.filter(project = project_id, info_check =1)
count = len(answer)
return count
There are many factors not included in the above, but what I want to solve is not to bring in the same queryset(Request, Answer).
The project itself is a structure that does not have attributes but is received only by foreign keys. Such a structure is making it difficult to find a solution.
I used select_related(prefetch_related too), but it does not work.
If you can give me some advice, I'd like to take some advice. thanks.
p.s. It is my first time asking question on this site, I apologize if there was anything rude.
admin.TabularInline will show the reverse foreign key in the admin detail page that may help you, but it seems that you have already used it in the inlines of ProjectAdmin.
is there any way to call a specific model custom method from a view? i need to subtract or increment depending on the view a field on my model, I want to create a button for each of the two options and after imputing that data update the field in my database. if so how can i go about implementing it, currently my save method is doing the two operations at once
models.py
class Items(models.Model):
nombre = models.CharField(max_length=250)
descripcion = models.CharField(max_length=250)
codigo_proveedor = models.CharField(max_length=250)
categoria = models.ForeignKey('Categorias', on_delete=models.CASCADE)
c_minima = models.PositiveIntegerField()
c_actual = models.PositiveIntegerField()
c_descuento = models.PositiveIntegerField(blank=True)
c_incremento = models.PositiveIntegerField(blank=True)
proveedor = models.ForeignKey('Proveedores', on_delete=models.CASCADE)
carrito = models.ForeignKey('Carrito', on_delete=models.CASCADE, null=True )
p_unitario = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True )
total = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
material = models.ForeignKey(Materiales, null=True, blank=True)
tipo = models.ForeignKey(Tipo, null=True, blank=True)
active = models.BooleanField()
def save(self, *args, **kwargs):
self.c_actual = self.c_actual - self.c_descuento
self.c_actual =self.c_actual + self.c_incremento
self.total = self.c_actual * self.p_unitario
super(Items, self).save(*args, **kwargs)
def __str__(self):
return '%s %s %s %s' % (self.nombre, str(self.categoria), str(self.c_actual), str(self.total))
You could use an instance method on the model e.g. exactly like the get_absolute_url().
You can add 3 methods in the model definition increment, decrement and total and write the respective logic in there.
So the view in the views.py file be something like
def some_view(request, *args, **kwargs):
#read the post data values from req
#create model instance
data = Items( #key value pairs)
#read from req to increament or decrement
if incr:
data.increament()
else:
data.decrement()
data.total()
data.save()
return render( ... )
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