Problems trying to populate sub form question fields with answers - django

First time poster here. I have been working on my first project for the last few months. And have spent an absorbent amount of time trying to get this one piece to work. I am able to display my configuration which has a drop down for config type. Depending on the Type selected it will display a list of "Attributes" (Questions) and I would like to have my form so that I can pick a type of config and answer the questions that pertain to that config. The part I am getting stuck on is the line in my view attrib_obj = get_object_or_404(config_attribs, id=1). This will display the first answer correctly for evey config because I hard coded it to show the answer to 1 but it will then display the first answer to every question. I am struggling on how to make this variable to be the id for every question and not just the first one. Thank you for any help. Oh and since i am new to this i am not sure if i am saving my form correctly either. :) Visual of my Problem
My Model
class Configuration(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
config_type = models.ForeignKey('ConfigType', on_delete=models.PROTECT, null=True)
company = models.ForeignKey('companies.Company', on_delete=models.PROTECT, blank=True, null=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("configurations:configuration-update", kwargs={"id": self.id})
class ConfigType(models.Model):
name = models.CharField(max_length=50, blank=False)
inactive = models.BooleanField(default=False)
def __str__(self):
return self.name
class Attribute(models.Model):
config_type = models.ForeignKey('ConfigType', on_delete=models.PROTECT, null=True)
number = models.IntegerField()
attribute = models.CharField(max_length=100, blank=False)
input_type = models.ForeignKey('InputType', on_delete=models.PROTECT, null=True)
required = models.BooleanField(default=False)
#answer = models.ManyToManyField('Answer')
inactive = models.BooleanField(default=False)
def __str__(self):
return self.attribute
class InputType(models.Model):
name = models.CharField(max_length=100, blank=False)
def __str__(self):
return self.name
class Answer(models.Model):
configuration = models.ForeignKey('Configuration', on_delete=models.PROTECT)
attribute = models.ForeignKey('Attribute', on_delete=models.PROTECT, null=True)
text = models.CharField(max_length=100, blank=True, null=True)
checkbox = models.BooleanField(blank=True, null=True)
number = models.IntegerField(blank=True, null=True)
date = models.DateField(blank=True, null=True)
def __str__(self):
return self.configuration.name + " - Attribute #" + str(self.attribute.number)
My View
#login_required(login_url='login')
def configuration_update_view(request, id=id):
obj = get_object_or_404(Configuration, id=id)
config_attribs = obj.config_type.attribute_set.all()
attrib_obj = get_object_or_404(config_attribs, id=1)
config_answers = obj.answer_set.all()
answer_obj = get_object_or_404(config_answers, attribute=attrib_obj)
form = ConfigurationForm(request.POST or None, instance=obj)
attrib_form = ConfigAttribForm(request.POST or None, instance=answer_obj)
if form.is_valid():
form.save()
if attrib_form.is_valid():
attrib_form.save()
context = {
'form': form,
'attrib_form': attrib_form,
'config_answers': config_answers,
'config_attribs': config_attribs
}
return render(request, "configurations/configuration_detail.html", context)

Related

Is there a way to update top level relationship in Django form?

I have below models and form.
Brand > Section > Category > Article.
I can pull the existing data out of the database however I have hit a wall. I am trying to create a new article or update an existing article but I'm not sure how I can update the brand, then the Section. The Category I can update and it is connected directly to the Article model. I have been thinking about this for a few days now and tried different models but ultimately i can't think of the best way to connect the models and have them update in the model.
class Brand(models.Model):
def brand_image(instance, filename):
return 'uploads/brand/{0}/{1}'.format(instance.title, filename)
title = models.CharField(max_length=50, unique=True, blank=True, null=True)
image = models.ImageField(upload_to=brand_image, null=True, blank=True)
slug = AutoSlugField(populate_from='title', unique_with='title', blank=True, null=True)
my_order = models.PositiveIntegerField(default=0, blank=False, null=False)
class Meta:
ordering = ['my_order']
def __str__(self):
return self.title or ''
def get_absolute_url(self):
return reverse('brand-list', kwargs={'brand_slug': self.slug})
class Section(models.Model):
title = models.CharField(max_length=50,unique=True, blank=True,null=True)
slug = AutoSlugField(populate_from='title', unique_with='title',blank=True,null=True)
brand = models.ForeignKey(Brand, on_delete=models.CASCADE, related_name='section', blank=False, null=False)
my_order = models.PositiveIntegerField(default=0, blank=False, null=False)
class Meta:
ordering = ['my_order']
def __str__(self):
return self.title or ''
def get_absolute_url(self):
return reverse('section-list', kwargs={'section_slug': self.slug})
class Category(models.Model):
title = models.CharField(max_length=50, blank=True,null=True)
slug = AutoSlugField(populate_from='title', unique_with='title',blank=True,null=True)
my_order = models.PositiveIntegerField(default=0, blank=False, null=False)
section = models.ForeignKey(Section, on_delete=models.CASCADE,related_name='category', blank=False ,null=False)
class Meta:
ordering = ['my_order']
def __str__(self):
return self.title or ''
def get_absolute_url(self):
return reverse('category-list', kwargs={'category_slug': self.slug})
class Article(models.Model):
title = models.CharField(max_length=100, unique=True, db_index=True)
description = models.CharField(max_length=100, blank=True, null=False)
category = models.ForeignKey(Category, on_delete=PROTECT, related_name='article', null=False, default=1)
slug = AutoSlugField(populate_from='title', unique_with='created__month')
content = HTMLField(null=True,blank=True)
internal = models.BooleanField(default=False)
status = models.CharField(max_length=30, choices=STATUS_CHOICES, default='Draft')
author = models.ForeignKey(User, related_name='author' ,on_delete=PROTECT,null=True)
updated_by = models.ForeignKey(User, related_name='updated_by',on_delete=PROTECT,null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
video = models.FileField(blank=True, null=True, upload_to='articles/videos')
favourites = models.ManyToManyField(User, related_name='art_favourite', default=None, blank=True)
tags = TaggableManager(related_name='tags', help_text='Comma or space separated list', blank=True)
pinned = models.BooleanField(default=False)
def __str__(self) -> str:
return self.title
def get_absolute_url(self):
return reverse('articles-detail', kwargs={'article_slug': self.slug})
class ArticleForm(forms.ModelForm):
title = forms.CharField(label='Article Title', max_length=100,)
description = forms.CharField(label='Description', max_length=100,required=False)
content = forms.CharField(label='Article Content',widget=CKEditorUploadingWidget(attrs={'cols': 80, 'rows': 30}))
video = forms.FileField(help_text="Valid file Extension - .mp4", required=False, validators=[validate_file_extension])
category = GroupedModelChoiceField(queryset=Category.objects.exclude(section=None).order_by('section'),choices_groupby='section')
internal = forms.BooleanField(required=False, help_text='Is this for internal use only?', label='Internal Article')
class Meta:
model = Article
exclude = ['slug','author','created','updated','updated_by','favourites','votes','views','section']
widgets = {"tags": TagWidget(attrs={"data-role": "tagsinput"})}
Any help or guidance would be greatly appreciated.
Your Article model has a foreign key link to Section for some reason. However your stated heirarchy and models use the following one-to-many relations, which creates a direct link up the chain.
Brand < Section < Category < Article.
This means that by choosing the Category you could also choose Brand and Section. If your Article had a foreign key link to Category instead, then all the information above about groups above Article could be obtained via the article, eg, article.category__section__brand. Changing the category would, by default, update section and brand. You could do this in a single dropdown that contained Category.objects.all - perhaps with the dropdown option text also containing brand and section info for clarity and sorting purposes.

Django Admin, show inline based on slug

Have the following models
class FootballWebsite(models.Model):
"""Football service website."""
url = models.URLField, unique=True)
#football service
id = models.CharField(primary_key=True,
#is this domain blocked
blocked = models.BooleanField(default=False)
#is it online or offline
online = models.BooleanField(default=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=True)
sub_categories = models.ForeignKey(SubCategory, default=1)
referral = models.TextField(blank=True)
mirror = models.ForeignKey('FootballWebsite', blank=True, null=True)
rank = models.PositiveIntegerField(default=0, blank=True, null=True)
screenshot = models.BooleanField(default=False)
class Meta:
"""Meta class."""
app_label = 'ahmia'
def __unicode__(self):
return u'%s' % (self.url)
"""The datetime when the football service was last seen online"""
try:
return self.footballwebsitestatus_set.filter(online=True).latest('time').time
except FootballWebsiteStatus.DoesNotExist:
return None
class FootballWebsiteDescription(models.Model):
"""Football service website description."""
about = models.ForeignKey(Footballebsite)
title = models.TextField(blank=True, null=True)
keywords = models.TextField(blank=True, null=True)
description = models.TextField(blank=True, null=True)
relation = models.URLField(blank=True, null=True)
subject = models.TextField(blank=True, null=True)
type = models.TextField(blank=True, null=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=True)
language = models.TextField(null=True, blank=True)
contactInformation = models.TextField(null=True, blank=True)
officialInfo = models.BooleanField(default=False)
slug = AutoSlugField(populate_from=['title'], allow_duplicates=True, null=True)
class Meta:
"""Meta class."""
app_label = 'ahmia'
def __unicode__(self):
return unicode(self.about.url)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(FootballebsiteDescription, self).save(*args, **kwargs)
def __unicode__(self):
return u'%s' % (self.title)
I have a huge amount of links, and i would like to bulk assign them into a category or mark them as blocked based on identical title slug.
Managed to at least get a list of title_slugs with the code below, but the following step, i would like to get an inline list with all sites that have an identical title_slug and bulk assign those all in their a category
class FootballWebsiteInline(admin.TabularInline):
model = FootballWebsite
class FootballWebsiteDescriptionAdmin(admin.ModelAdmin):
list_display = ['show_slug']
def show_slug(self, obj):
return format_html("<a href='{url}'>{url}</a>", url=obj.slug)
inlines = [
FootballWebsiteInline,
]
Above code obviously doesn' t work, since the title slug which can appear many times is not a primary key.
Is it possible to get an inline list based on the title slug in this case which is not a primary key at all, or am i going about this the wrong way?
When possible at all, some further tweaking would be to group the identical title slugs

How can I apply logic is the user present in the Frontend Order Model?

I just want If a user Ordered something then the user will be able to rate on the order else can't and will show an error message "You didn't purchase any website". I applied logic 5/6 times in different ways but I couldn't fix the issues.
Oeder Model:
class Frontend_Order(models.Model):
USer = models.ForeignKey(User,default=None,on_delete=models.CASCADE,related_name='user_frontend_order')
Service_Type = models.CharField(max_length=250, null=True)
Price = models.CharField(max_length=250, null=True)
Number_of_Section = models.CharField(max_length=250, null=True)
Per_section_Price = models.CharField(max_length=250, null=True)
Website_Functionality = models.CharField(max_length=50, null=True)
Email = models.EmailField(max_length=50, null=True)
files = models.FileField(upload_to="0_frontend_files/", null=True, blank=True)
created_date = models.DateTimeField(auto_now_add=True, null=True)
order_message = models.ForeignKey(Message_Manu,on_delete=models.CASCADE, null=True, related_name="message")
def __str__(self):
return str(self.pk)+ str(".") + str(self.USer)
Rating Model:
class Frontend_Rating(models.Model):
USer = models.OneToOneField(User,default=None,on_delete=models.CASCADE, related_name="frontend_rating")
Rating = models.IntegerField(null=True)
Feedback = models.TextField(max_length=250, null=True)
created_date = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return str(self.pk)+ str(".") + str(self.USer) + str("(") + str(self.Rating) + str("stars") +str(")")
Order View:
def frontend_order_rating(request):
if request.user.is_authenticated:
if request.method == "POST":
frontend_rating = int(request.POST.get('frontend_ratting'))
frontend_feedback = request.POST.get('frontend_feedback')
try:
Frontend_Rating.objects.create(
USer = request.user,
Rating = int(frontend_rating),
Feedback = frontend_feedback
)
messages.success(request,f"{request.user.first_name}, Thank You for your feedback!")
return redirect("/", userz = request.user)
except:
messages.error(request,f"{request.user.first_name}, Sorry! You've already given a feedback!")
return redirect("/", userz = request.user)
else:
messages.error(request,"Please login or create an account.")
return redirect("/")
first check if the user ever did an order by
if Frontend_Order.objects.filter(USer=request.user.id):
# your code for thanking for feedback
else:
# your code for sorry

Update another model's object after a form submit

I am attempting to update another model's object after a form submit. I would like the single object, already in existence within the Savings model, updated to reflect the most recent Entry submission.
Process:
Once the Entry form is filled out and submitted, I need the Savings object, which contains the "total" fields, to be updated.
The Savings fields take data from the Entry form, sums it, and posts it to its corresponding fields. For example, Savings.total_spent_euros sums Entry.euros_sums, and Savings.total_spent_dollars sums Entry.dollars_sum. That logic is not the issue. The problem I have is I currently have to open the Savings object in admin and save it every time I want the object to include the most recent entries. I would like to automate that.
models.py
class Entry(models.Model):
date = models.DateField(blank=True, null=True,)
euros = models.CharField(max_length=500, blank=True, null=True)
comments = models.CharField(max_length=900, blank=True, null=True)
euros_sum = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
xrate = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
dollars_sum = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
daily_savings_dollars = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
daily_savings_display = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
def get_absolute_url(self):
return reverse('argent:detail', kwargs={'pk': self.pk})
class Savings(models.Model):
total_spent_euros = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
total_spent_dollars = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
total_savings = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
total_savings_display = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
Am I assuming correctly that my command must be entered within these two views? (I could be wrong):
views.py
class EntryCreate(CreateView):
form_class = EntryForm
template_name = 'argent/entry_form.html'
def form_valid(self, form):
Savings.objects.update(id=1)
return super(EntryCreate, self).form_valid(form)
class EntryUpdate(UpdateView):
model = Entry
form_class = EntryForm
template_name = 'argent/entry_form.html'
def form_valid(self, form):
Savings.objects.update(id=1)
return super(EntryUpdate, self).form_valid(form)
However, whenever I use Savings.objects.update(id=1) or Savings.objects.filter(id=1).update(), nothing happens. What am I overlooking here?
Thanks in advance for your help!
EDIT: Added a bit more detail.
SOLUTION
With the help of nik-m we finally came up with a solution. Here is my updated views.py. Not only did I have to use the .update solution, but I had to include all of the logic that is otherwise housed within my forms.py.
views.py
class EntryCreate(CreateView):
form_class = EntryForm
template_name = 'argent/entry_form.html'
def form_valid(self, form):
if form.save(self):
# total_euros_spent
sum_euros = Entry.objects.aggregate(s=Sum('euros_sum')).get('s')
sum_euros_f = "{0:.2f}".format(sum_euros)
# total_dollars_spent
sum_dollars = Entry.objects.aggregate(s=Sum('dollars_sum')).get('s')
sum_dollars_f = "{0:.2f}".format(sum_dollars)
# total_sum
sum_savings = Entry.objects.aggregate(s=Sum('daily_savings_dollars')).get('s')
sum_format = "{0:.2f}".format(sum_savings)
# total_sum_format
sum_abs_savings = Entry.objects.aggregate(s=Sum('daily_savings_dollars')).get('s')
absolute = abs(sum_abs_savings)
sum_abs = "{0:.2f}".format(absolute)
Savings.objects.filter(id=1).update(total_savings=sum_format, total_savings_display=sum_abs,
total_dollars_spent=sum_dollars_f, total_euros_spent=sum_euros_f)
return super(EntryCreate, self).form_valid(form)
else:
return self

django class-based views key word

I've been following the manual for generic views for Django 1.4, but can get the 'list books by publisher' example to work. My site is slightly different in that I'm trying to list bookings of a property by the name (or id) of the person who books the property. People will book more than once, so I want to be able to see what their bookings were.
My views.url for this is:
class GuestBookingListView(DetailView):
context_object_name = 'guest_booking'
template_name = 'guest_booking.html'
def get_queryset(self):
self.guest = get_object_or_404(Guest)
return Booking.objects.filter(guest = self.guest)
def get_context_data(self, **kwargs):
context = super(GuestBookingListView, self).get_context_data(**kwargs)
context['guest'] = self.guest
return context
My model is:
class Guest(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=50)
spouse_first = models.CharField(max_length=30, blank=True)
spouse_last = models.CharField(max_length=50, blank=True)
num_child = models.IntegerField(verbose_name='Number of children')
address = models.TextField(max_length=50, blank=True)
city = models.CharField(max_length=60, blank=True, verbose_name='Town / City')
state_province = models.CharField(max_length=30, blank=True, verbose_name='County')
post_code = models.CharField(max_length=8, blank=True)
country = models.CharField(max_length=50, blank=True)
email = models.EmailField(blank=True)
landline = models.CharField(max_length=25, blank=True)
mobile = models.CharField(max_length=25, blank=True)
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Booking(models.Model):
guest = models.ForeignKey(Guest)
ack_date = models.DateField(verbose_name='Date acknowledged')
start_date = models.DateField(verbose_name='Start date')
end_date = models.DateField(verbose_name='End date')
dep_recd = models.DateField(null=True, blank=True, verbose_name='Deposit received')
bal_recd = models.DateField(null=True, blank=True, verbose_name='Balance received')
keys_sent = models.DateField(null=True, blank=True, verbose_name='Date keys sent')
sec_retn = models.DateField(null=True, blank=True, verbose_name='Security deposit returned')
rtm_sent = models.IntegerField('Status', blank=True)
notes = models.TextField(blank=True, verbose_name='Notes')
and my urls.py is:
url(r'^guests/(?P<pk>\d+)/$', GuestBookingListView.as_view (
#context_object_name = 'booking_list',
)),
So far as I can see this identical (with different field names) to the example, but the result I get is:
get() returned more than one Guest -- it returned 26! Lookup parameters were {}
The 'get' is retrieving all of the Guests in the database, not the one which I've selected.
I've spent hours of searching and experimenting on this, but to no avail. If I put 'guest = 11' it works, so there's something wrong with the pk.
Thank you!
You haven't given any sort of criteria to get the guest. You've just said, in effect, "give me guest", and Django has given you all 26 of them. If you want to filter by the pk kwarg, you should say so:
self.guest = get_object_or_404(Guest, pk=self.kwargs['pk'])