Custom Field Type or Logic in the View? - django

Before I start on this project I want make sure what I am proposing is feasible. There is an unusual requirements I have to satisfy.
The model and formModel fields have to support a comment field on every field. I would like to be able to access them by object.field and object.field.comment. At first glance, this looks like I should have a separate type of comment and then somehow link it to correct field but is there a way to create a custom modelField that stores data in more then one database field from one or more form inputs? I would think there would have to be a custom widget to support this too?
If anyone has any ideas or examples of anything like this please respond.

I think this is the answer to my question. I have not tried it yet, but from the description it looks like what I need. https://docs.djangoproject.com/en/dev/ref/forms/widgets/#multiwidget

Related

Flask WTF SelectField with custom entry?

I want to create a SelectField that offers suggestions but still allow the user to enter something else.
class MyForm(Form):
username = wtf.StringField()
title = wtf.SelectField('Job title', choices=['Owner', 'Manager'], validate_choices=False)
WTF documentation suggests that setting validate_choices to False allows this:
Note the validate_choice parameter - by setting this to False we are telling the SelectField to skip the choice validation step and instead to accept any inputted choice without checking to see if it was one of the given choices.
But, no data entry or modification is possible with above. Is this possible or do I need another 'manual entry' field?
Or, is there perhaps a way to show my suggestions in a StringField using JS similar to the way the browsers offer autocomplete suggestions for addresses etc?
I'm not aware of any way to do this. It seems you and I are in a similar position. However, I did have an idea I wanted to share that could work for you.
Many forms will have a dropdown with a value "Other" and if you select "Other" there is another empty box that appears for you to type in. You could implement this pretty easily in wtforms. Alternatively you could have the extra box always display and just do a check that they did indeed select "Other" if they have a custom input.
I have opened an issue, but they are not planning to add this feature.
Based on this, we could, but it is not a pure python implementation

Check which fields are changed in Django

I have a model with many fields. I need to run a code only when two specific fields are changed. I know I can modify my model's save() method but I don't know how to check which fields are changed in my ModelForm.
Sorry because i cant give you any code snippet since i am not very experienced in Django, but i would go for getting a signal when a change is done through a controler class listening on the models and hearing for changes. Hope i might helped a bit.
Good luck
Django-model-utils has something called a FieldTracker that does exactly this. Just instantiate it in your model and tell it to track the specific fields you're looking for. Then you can use the has_changed method to test if a given field has changed since the last save.
This package has some other great utilities as well, I really recommend looking through the docs.
You could try django-dirtyfields.

Query on a Many to Many relationship using through in Django

I'm new in Django and I'm giving myself a big headhache trying to structure this query.
I have a BaseProfile connected with a OneToOne field to User.
I'm specializing the profile in CustomerProfile connected with a OneToOne field to BaseProfile.
A CustomerProfile has a ManyToMany relationship with other CustomerProfile (so itself) through a RelatedCustomer model.
In the RelatedCustomer I specify the from_customer and to_customer Foreign Keys.
Maybe with an image you can understand better.
My problem:
Given a user.id I need to know all the other user.id of the customers that he is connected to (so passing through from_customer and to_customer):
So basically, first I need to dig from User to RelatedCustomer using reverse lookup, take all the set, and then going back to know the user.id of each customer in the set.
EDIT2:
What I've reached so far:
# This gives me back a customer profile given a user.id (2)
cm = CustomerProfile.objects.get(base_profile__user=2)
# M2M lookup. Given one customer returns all the RelatedCustomer relations
# that he has as a part of the 'from' M2M
cm.from_photographer.all()
Chaining the previous two: given a user.id I obtain a queryset of CustomerRelated relations:
rel = CustomerProfile.objects.get(base_profile__user=2).from_photographer.all()
This gives me back something like:
[<CustomerRelated: from TestCustomer4 to TestCustomer2 >,
<CustomerRelated: from TestCustomer4 to TestCustomer3 >]
Where in this case the user having a user.id=2 is the TestCustomer4.
My question:
So far so good, but now having this set how can I get all the user.id of the to_customer?
That is, how do I get the user.id of TestCustomer2 and TestCustomer3?
Firstly, this is not how you query the database in django. Secondly (since you're learning), it would be good to point out that you can run dbshell to try out different things. And lastly, this kind of problem is described in the documentation.
I am telling you this, because as a beginner, I also felt that it was a little difficult to navigate through the whole thing. The best way to find things is just to use google, and add a django at the end.
I know how you feel, the documentation search sucks, right? Heh, I feel you, that is why you always search the way I described it. Once you get a hang of the documentation, you will feel that the documentation title page is a little more intuitive.
Okay, so now to the answer:
To access a ManyToMany, OneToOne or ForeignKey field, you need to use a __ commonly known as dunder.
So, this is how I would go about doing this. Please note that there are other ways, and potentially better ways of doing this:
thing_I_want = RelatedCustomer.objects.get(to_customer__id=2)
Note, however that if you wanted to get a list of customers you would use filter(). Here is an example (which uses number of purchases as an example):
things_I_want = RelatedCustomer.objects.filter(to_customer__no_of_purchases=16)
Also note that the great thing about filter is that you stack one filter on top of another. You can read more about these features in the documentation link I provide below.
That will get you what you want. Now, you might have more queries regarding this, and how it all works together. Not to fear, please click this documentation link to check it out.
EDIT
Seems like what you want to do can be done by django, but if you want to do it using sql, then that is possible too. For example, SomeModel.objects.raw("SQL_HERE"). The name of the tables are usually <app>_<model>.
However, what you are asking can also be done in django, using the ORM. But it will be tricky.
Ok, as usual whenever you get the answer it always look much more easier than what you were expecting.
I guess this worked for me:
User.objects.filter(base_profile__customer_profile__to_customer__in=
User.objects.get(id=2).base_profile.customer_profile.from_customer.all())
Many thanks to #Games Brainiac

Django:Bind comments to any object

I am developing a custom commenting solution for my webapp.Can anyone tell me what's the logic behind binding comments to any model's object?I want to do something like {% customcomment%}.Django comments framework already does this.
https://docs.djangoproject.com/en/dev/ref/contrib/comments/
the comments framework uses Content Types and generic relations to attach a comment to any record of any model.
https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#module-django.contrib.contenttypes
https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1
ALSO
you can extend django comments if you need to do something custom. you shouldn't need to roll your own. What specifically are you trying to achieve?

Specifying default value for django hidden form field - bone DRY?

So let's say at the last minute (in the view) I decide I want to specify a default for a field and make it hidden, like so:
form.fields['coconut'] = forms.ModelChoiceField(
label="",
widget=forms.HiddenInput(),
queryset=swallow.coconuts.all(),
initial=some_particular_coconut,
)
My question is this: Do I really need to specify queryset here? I mean, I already know, from initial, exactly which coconut I'm talking about. Why do I also need to specify that the universe of available coconuts is the set of coconuts which this particular swallow carried (by the husk)?
Is there a way I can refrain from specifying queryset? Simply omitting causes django to raise TypeError.
If indeed it is required, isn't this a bit damp?
I think is good that stackoverflow answers point to the 'right' way to do things, but increasingly the original question goes unanswered because the user was trying to do the wrong thing.
So to answer this question directly this is what you can do:
form.fields['coconut'] = forms.ModelChoiceField(label="", widget=forms.HiddenInput(attrs={'value':some_particular_coconut}), queryset=swallow.coconuts.all())
Notice the named argument passed to HiddenInput, its super hackish but its a direct answer to the original question.
The problem is that you're trying to set up a hidden ModelChoiceField. In order to have a Choice (dropdown, traditionally) it needs to know its Choices - this is why you give a queryset.
But you're not trying to give the user a choice, right? It's a hidden input, and you're setting it from the server (so it gets POSTed back, presumably).
My suggestion is to try to find a way around using the hidden input at all. I find them a bit hacky. But otherwise, why not just specify a text field with some_particular_coconut.id, and hide that? The model's only wrapping that id anyway.
The reason django requires a queryset is because when you render the field to the page, django only sends the id. when it comes back, it needs knowlege of the queryset in order to re-inflate that object.
if you already know the queryset at form creation time, why not simply specify form.fields['coconut'].initial = some_particular_coconut in your view and leave the rest of the definition in your forms.py?
If you find that you only really need to send the id anyway (you don't have to re-inflate to an object at your end), why not send it in a char field?