Django: Generate form from dictionary - django

I'm currently working on a django-app where users have the option to select synonyms for a select number of words. These words are then replaced all over the website by these synonyms
these synonymes are defined as a separate model:
class TransportSynonyms(models.Model):
user= models.ForeignKey(user)
key = models.CharField(max_length=255)
value = models.CharField(max_length=255)
This process is done in part with template tags, and as such the number of words that can be 'synonymed' is limited. For example, the following words can be replaced by synonymes:
'train', 'plane'.
And appear like so in the html template:
{% get_trans "train" %}
{% get_trans "plane" %}
I now want to give user the ability to define synonymes for themselves, without the admin view. I created a few pages using a ListView as an overview (so the users could see which words they can change) with individual buttons that led to EditViews.
However, I'm since user have no synonyms linked to them by default, the ListView appears empty. I could solve that by passing a list from the view, but that list wont have the required '.id' values and would be worthless for linking to the EditViews.
My listview currently looks like the following table:
Original | Synonym
---------------------------
train | train (button to editview)
plane | aircraft (button to editview)
The buttons require an ID value
href="{% url 'synonym_edit' pk=synonym.id %}"
I have to find a way to fill the ListView with the 'synonymable' words and provide links to a DetailView (for synonyms might not yet exist).
I thought about dropping the ListView all together and instead pass a dictionary to a form. By default both the key and the value will be the same word
({'train' : 'train', 'plane' : 'plane'})
and a form would then be generated form this dictionary, allowing users to change the value by having the dictionary value be shown as a text input.
Its a bit more limited (and more cumbersome) than my original plan, but I think this might work. Problem is that I've only really worked with modelforms before, and I am currently stuck on having the form be generated from the dictionary. Could anyone here point me to the right direction?
Regards,
Jasper

Related

Can we enter html code in a field in models in django?

I am making a small static website in which I have a template in which I tend to show the privacy policy terms of usage etc. I currently don't have any matter for it and tend to add it in future after deploying the site on server. I wanted to know that if I can in future add the matter on that page through a model i.e I create a model with two fields privacy policy , terms and in and pass it to the template as context in views.py . But I have a concern that the fields will have several headings which I will have to display in bold , so is there any way that I can pass html tags in model field and when I render it in my template as {{privacy}} the part I want in bold or any other style comes as that style.
So is there any way that I can pass html tags in model field and when I render it in my template as {{privacy}} the part I want in bold or any other style comes as that style.
Yes. You only need to tell the Django template engine not to escape the characters (for example translate < to <). You can do this with the |safe template tag [Django-doc]:
{{ privacy|safe }}

Django ManyToMany field using through with relational value

I have a model with many to many field, the field it linked through a table with Boolean value.
I got this in different scenario, lets take user as the main model, interest as the many to many field and user_interest model as the through model, inside user_interest I have a Boolean field which I want user to specify when selecting each of his many to many value,
At the moment am stuck trying to find an appropriate form interface to cater for my need, currently am using MultipleSelect widget which only show selection of interest, is there any example for field control that would allow me to choose the interest and specify the value of the Boolean field? If not, what is best practice to follow in my situation?
Best regards,
Update question with code samples
class Interest(models.Model):
name = models.CharField(_('Name'), max_length=200, )
class UserInterest(models.Model):
interest = models.ForeignKey(Interest, )
user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL'), )
join_mail_list = models.BooleanField(default=False)
class User(models.Model):
name = models.CharField(max_length=100)
interest = models.ManyToManyField(Interest, through='UserInterest', related_name='user_interest')
Now based on the models above, when I try to create a ModelForm from User model, I will get interest as MultiSelect field which is perfectly correct. But, in my case, I want the form to collect user interests + for each interest if he wants to join_mail_list for that particular interest. Please advise?
I'll just assume that you want a list of all interests with a checkbox next to them.
Let's assume those models:
class Ressource(models.Model):
name = models.CharField(max_length=255)
class Ressource2Village(models.Model):
ressource = models.ForeignKey(Ressource)
village = models.ForeignKey(Village)
amount = models.FloatField()
class Village(MapObject):
name = models.CharField(max_length=255)
And this form:
class Ressoure2VilllageForm(forms.Form):
name = forms.CharField()
# you would use a BooleanField
value = forms.IntegerField()
Now you can create a formset (https://docs.djangoproject.com/en/1.5/topics/forms/formsets/):
from django.forms.formsets import formset_factory
r2v_formset = formset_factory(Ressoure2VilllageForm)
# use boolean for your case, if you want to edit these values later use n2m to initialize value
# [{'name': r2v.ressource.name, 'value': r2v.value} for r2v in your_village.ressource2village.all()]
init_values = [{'name': r.name, 'value': 0} for r in Ressource.objects.all()]
r2v_formset = r2v_formset(initial=init_values)
Which in your template will give you:
<label for="id_form-0-name">Name:</label><input type="text" name="form-0-name" value="Kohle" id="id_form-0-name">
<label for="id_form-0-value">Value:</label><input type="text" name="form-0-value" value="0" id="id_form-0-value">
<label for="id_form-1-name">Name:</label><input type="text" name="form-1-name" value="Eisenerz" id="id_form-1-name">
<label for="id_form-1-value">Value:</label><input type="text" name="form-1-value" value="0" id="id_form-1-value">
<label for="id_form-2-name">Name:</label><input type="text" name="form-2-name" value="Golderz" id="id_form-2-name">
[...]
The association to the specific user can be done during processing under consideration of his authentication details.
Displaying, validating and processing this should be pretty straightforward, feel free to ask follow up questions.
The question is kind of general, but I'd say that since it's a boolean field, instead of one multiselect field, you have two - one for "Things I'm interested in..." (True) and one for "Thing's I'm not interested in..." (False). Both fields would be multiselect from the same list of items, but the seperation allows the user to apply the boolean field without even noticing. Also, I strongly recommend jQuery UI autocomplete, seems like the best choice here.
Updated answer:
So seeing your code helps clear a few things. The way I would do it is like I suggested in the first place but with a little tweak.
Having a newsletter checkbox for each 'interest' is clumsy, because it requires the user to check the 'interest' twice - once because he's interested in it and once because he wants emails about it. So you have to automatically assume that the user wants to get an email for the subjects he is interested in, but allow them to prevent it if they want.
With that in mind, you build two long text inputs, and implement both of them with a tagging system (here's a good one, here are some more). The first input is "I'm interest in", and the second is "I want to recieve emails about...". Then you add an event listner with jQuery that makes sure that for every tag added to the first input it is automatically added to the second one as well. Then, if the user doesn't want to get emails for a specific subject (or all of them) he can easily take it off the second input (which doesn't have any effect on the first one).
To give you an example, here's a jsfiddle that shows how to make that happen with the chosen-jQuery library. I used Countries and Shipping because I had a pre-made list at the chosen library website, so I just copied it from there. As you can see, it's a pretty simple jQuery code, which you can easily applicate for any other tagging system (and many thanks to the fine Raúl Juárez who helped me work that out myself):
$(".chosen-select").chosen({disable_search_threshold: 10});
$('#countries').on('change', function(e) {
var selected = $(this).val();
$.each(selected, function(index, value) {
$('#shipping option[value="'+value+'"]:first').prop('selected',true);
});
$(".chosen-select").trigger('chosen:updated');
});

Putting links in list_detail.object_list to list_detail.object_detail

I've started using Django and am going right to generic views. Great architecture! Well, the documents are great, but for the absolute beginner it is a bit like unix docs, where they make the most sense when you already know what you're doing. I've looked about and cannot find this specifically, which is, how do you set up an object_list template so that you can click on an entry in the rendered screen and get the object_detail?
The following is working. The reason I'm asking is to see if I am taking a reasonable route or is there some better, more Djangoish way to do this?
I've got a model which has a unicode defined so that I can identify my database entries in a human readable form. I want to click on a link in the object_list generated page to get to the object_detail page. I understand that a good way to do this is to create a system where the url for the detail looks like http://www.example.com/xxx/5/ which would call up the detail page for row 5 in the database. So, I just came up with the following, and my question is am I on the right track?
I made a template page for the list view that contains the following:
<ul>
{% for aninpatient in object_list %}
<li><a href='/inpatient-detail/{{ aninpatient.id }}/'>{{ aninpatient }}</a></li>
{% endfor %}
</ul>
Here, object_list comes from the list_detail.object_list generic view. The for loop steps through the object list object_list. In each line I create an anchor in html that references the desired href, "/inpatient-detail/nn/", where nn is the id field of each of the rows in the database table. The displayed link is the unicode string which is therefore a clickable link. I've set up templates and this works just fine.
So, am I going in the right direction? It looks like it will be straightforward to extend this to be able to put edit and delete links in the template as well.
Is there a generic view that takes advantage of the model to create the detail page? I used ModelForm helper from django.forms to make the form object, which was great for creating the input form (with automatic validation! wow that was cool!), so is there something like that for creating the detail view page?
Steve
If you're on django < 1.3 then what you are doing is basically perfect. Those generic views are quite good for quickly creating pages. If you're on django 1.3 you'll want to use the class based generic views. Once you get a handle on those they are are crazy good.
Only note I have is that you should use {% url %} tags in your templates instead of hardcoding urls. In your urls.conf file(s) define named urls like:
url('inpatient-detail/(?P<inpatient_id>\d+)/$', 'your_view', name='inpatient_detail')
and in your template (for django < 1.3):
...
In 1.3 a new url tag is available that improves life even more.

is there a way to use django generic views and some smart urlpatterns for quick ordering/sorting of queries?

let's assume I have a django model like this:
class Event(CommonSettings) :
author = models.ForeignKey(User)
timestamp = models.DateTimeField(auto_now_add=True)
event_type = models.ForeignKey(Event_Type, verbose_name="Event type")
text_field = models.TextField()
flag_box = models.BooleanField()
time = models.TimeField()
date = models.DateField()
project = models.ForeignKey(Project)
now, by default, I have a view where I sort all events by time & date:
event_list = Event.objects.filter().order_by('-date', '-time')
however, maybe the user wants to sort the events by time only, or by the date, or maybe in ascending order instead of descending. I know that I can create urlpatterns that match all these cases and then pass on the these options to my view, however I feel like I'm reinventing the wheel here. the django admin site can do all of this out of the box.
So here's my question: is there a clever, easy way of getting this done in a generic way, or do I have to hard code this for my models / views / templates?
and yes, I did find solutions like this (https://gist.github.com/386835) but this means you use three different projects to achieve one thing - this seems to be a too complicated solution for such a simple thing.
EDIT1:
how do I have to change the template so that I can combine multiple filters? Right now I have
Desc
Asc
but I want to allow the user to also change number of entries that get displayed. So I have:
order by date
order by name
This works all fine, but if I click on 'order by date' and then I click on 'Asc', then my previously selected order disappears. That's not what I want. I want the user to be able to combine some options but not others.
EDIT2:
unfortunately your solution doesn't work with
from django.views.generic.list_detail import object_list
and it's
paginate_by
option.
I tried:
prev
{% trans "next" %}
but the links then just don't work (nothing happens). maybe you need to do something special with "object_list"?
I don't think it's as much work as you're making it out to be - you can use variables instead of explicitly creating separate url patterns. If you look at how the django admin handles it, they tack on request variables to the url like ?ot=asc&o=2 This corresponds to sort in ascending order in by the 2nd column. Of course, if you designing a particular page, you might as well use more readable naming. So instead of numbering the categories, i'd do ?sort=desc&order_by=date and then put a regular expression in the view to match the different possibilities. Something like:
order = re.match(r"(?:date|time|name)$", request.GET['order_by'])
if request.GET['sort'] == 'desc':
order = '-' + order
results = Event.objects.filter().order_by(order)
You could instead use the regexp as a url pattern matcher as you suggested, but it's more common to let the url itself represent which part of the site you're at (i.e. website.com/events/) and the url request variables represent how that content is being displayed (i.e. ?order_by=date&sort=desc).
Hope that helps!
EDIT: For the second part of your question, use Django's templating system (which reads variables) instead of just html. There are several ways I can think of to do this, depending on personal preference and how exactly you want the UI to function (i.e. page loads with new variables anytime the user chooses a filter, or the user chooses all filter options in a form and then submits it so the page only has to reload once, etc). In this case, you could just do:
Ascending
Descending
Name
Date
Then in the view make sure your render_to_response arguments include a dictionary that looks like: {'order': request.GET['order_by'], 'sort': request.GET['sort_by'], }
Unfortunately, (and someone please correct me if I'm wrong) I don't think there's a template tag to generate a url with request.GET parameters - the url tag {% url name_of_view order_by=name sort_by=desc %} would generate "path/to/name_of_view/name/desc/", but I don't think there's a tag to generate "path/to/name_of_view?order_by=name&sort_by=desc". It would be pretty easy to write a custom tag for this though (I wouldn't be surprised if there's already one on django-snippets or something, although I just did a quick google search and didn't find anything).

django pagination: How to get number of page by id of element in the list

I use django-paginaton app and I'm very glad to use it. Now I need feature, that I don't know how to implement. I have list of elements, that paginated by django's paginator. I have one element with specified id, that I should show, but I don't know what page contains it. I need mechanism jump to the page, that contains my element.
I think it's a good idea if django-pagination will support this transparently and automatically. For example, I set special context variable page_by_id to X and if page is None, it will be defined to the value, that contains my X element.
What do you think about this mechanism?
May be there is another clean way to do this?
This is for continue of this questions:
Django pagination and "current page"
Django Pagination - Redirecting to the page an object is on
At least, I wrote patch for django-pagination that provide 2 features:
Get number of page by id of element inside paginated list;
Possibility to rename default parameter 'page' to another value for
using it inside template;
This works transparently by adding 2
optional parameters in autopaginate templatetag:
{% autopaginate object_list paginated_by orphans page_by_id parameter_name %}