I'm currently building a Django website where staff has control over users, and, within those powers, I'd like to add one where the staff members can add private comments on users so that they can be read by whoever has the power to do so.
So I started building the user models.py here what I did:
class user(models.Model):
name = models.CharField(max_length=30)
comments = models.TextField()
date = models.DateField(default=datetime.now())
def __str__(self):
return self.name
My question: how can I add a comment field every time a staff member wants to? Like, with the above code, I can only have one comment per user.
Everything is appreciated.
Thanks!
There are a few ways to do this.
1. ForeignKey
Make a separate model for the comments and have a ForeignKey to the User model. That way, multiple comments can be linked to the same user.
2. ArrayField
If you're using Postgres database, you can use the ArrayField.
Cons: Editing in the admin panel is not very user friendly.
3. JSONField
You can also keep multiple comments in a JSON array.
Cons: Editing in the admin panel is not user friendly.
P.S.: If you decide to use either ArrayField or JSONField, check out an app I've made called django-jsonform. This will make editing JSON and ArrayField nice and user-friendly.
Related
I'm am building a django app which takes user Interests as inputs.
Now I have 2 Questions -
First is that, what model should I use, should I just add a field to user model or a separate Interest Model and link via Foreign Key?
I know the former design is bad, and so I.m trying latter one, I'm having a hard time in Django to create Interest Model and its view to save the user interests.
Any help is appreciated.
I am trying to accomplish the same thing.
Here is how I have solved it:
I have not tried it out yet, but this should work as a solution.
from django.contrib.auth.models import User
class Nation(models.Model):
name=models.CharField(max_length=64)
class Subject(models.Model):
name=models.CharField(max_length=64)
class Interests(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
nationals = models.ManyToManyField(Nation)
subjects = models.ManyToManyField(Subject)
I have a model created in Django 1.5 as below:
class Number(models.Model):
phone_number = models.CharField("Phone Number", max_length=10, unique=True)
I set up Django admin as below:
from django.contrib import admin
from demo.models import Message, Number, Relationship, SmsLog
class NumberAdmin(admin.ModelAdmin):
search_fields = ['phone_number']
admin.site.register(Number, NumberAdmin)
I believe Django add "date_created" column to the database automatically (because I know it sorts the data entries by creation time in admin console). Is there a way to view those time/dates in admin console? The closest I have go to is Django tutorial and StackOverflow ,but I do not want to create another column on my own (pub_date in Django official tutorial's example) and add it if possible. Is there a way to do it and if so, could someone show me how to? Thank you!
Django does not automatically add a date_created column. If you want to track the creation date, you have to declare it in your model.
You may be getting the illusion that it does because if you do not specify a sort order in the model or in the admin class for the model, it will default to sorting by primary key, which will increase according to the order the model instances were created.
Lets say for example I have a Model called "Client" and a model called "PhoneNumbers"
class PhoneNumbers(models.Model):
number = forms.IntegerField()
class Client(models.Model):
number = forms.ManyToManyField(PhoneNumbers)
Client has a ManyToMany relationship with PhoneNumbers. PhoneNumbers has almost 500,000 records in it so when it comes to editing a Client record from a model form with a MultiSelect widget that comes with a M2M filed, it takes forever to load. In fact, it never does. It just sits there trying to load all of those phone objects I am assuming.
My workaround was to so some tedious things with ajax and jquery to edit only the phone numbers in a Client record. Before wasting my time with all of that I wanted to see if there is somehow another way to go about it without having my page hang.
You need to create a custom widget for this field that lets you autocomplete for the correct record. If you don't want to roll your own: http://django-autocomplete-light.readthedocs.io/
I've used this for its generic relationship support, the M2M autocomplete looks pretty easy and intuitive as well. see video of use here: http://www.youtube.com/watch?v=fJIHiqWKUXI&feature=youtu.be
After reading your comment about needing it outside the admin, I took another look at the django-autocomplete-light library. It provides widgets you can use outside the admin.
from dal import autocomplete
from django import forms
class PersonForm(forms.ModelForm):
class Meta:
widgets = {
'myformfield': autocomplete.ModelSelect2(
# ...
),
}
Since Django 2.0, Django Admin ships with an autocomplete_fields attribute that generates autocomplete widgets for foreign keys and many-to-many fields.
class PhoneNumbersAdmin(admin.ModelAdmin):
search_fields = ['number']
class ClientAdmin(admin.ModelAdmin):
autocomplete_fields = ['number']
Note that this only works in the scope of Django admin of course. To get autocomplete fields outside the admin you would need an extra package such as django-autocomplete-light as already suggested in other answers.
Out of the box, the model admin has a raw_id_fields option that let your page load much quicker. However, the user interface of raw id fields isn't very intuitive, so you might have to roll your own solution.
We use this 3rd party widget for this:
https://github.com/crucialfelix/django-ajax-selects
Btw, your 'example' above is really bad DB design for a bunch of reasons. You should just have the phone number as a text field on the Client model and then you would have none of these issues. ;-)
edit: I wasn't clear before, I am saving my object in the django admin panel, not in a view. Even when I save the object with no many-to-many relationships I still get the error.
I have a model called TogglDetails that has a ForeignKey relationship with the standard django User model and a MayToManyField relationship with a model named Tag. I have registered my models with django admin but when I try to save a TogglDetails instance I get the error in the title.
Here are my models:
class Tag(models.Model):
name = models.CharField(max_length=30)
def __unicode__(self):
return self.name
class TogglDetails(models.Model):
token = models.CharField(max_length=100)
user = models.ForeignKey(User)
tags = models.ManyToManyField(Tag, blank=True, null=True)
def __unicode__(self):
return self.user.username
class Meta:
verbose_name_plural = "toggl details"
As far as I can tell, there should be no issues with my models and django admin should just save the instance without any issues. Is there something obvious that I have missed?
I am using Django 1.3
The answer to my question was this: Postgres sequences without an 'owned by' attribute do not return an id in Django 1.3
The sequences in my postgres database did not have the "Owned by" attribute set and so did not return an id when a new entry was saved to the db.
As stated by other users:
Postgres sequences without an 'owned by' attribute do not return an id in Django 1.3
The sequences in my postgres database did not have the "Owned by" attribute set and so did not return an id when a new entry was saved to the db
In addition:
This is most likely caused by a backwards incompatible change that renders some primary key types in custom models beyond reach for Django 1.3. See Django trac tickets https://code.djangoproject.com/ticket/13295 and http://code.djangoproject.com/ticket/15682 for more information.
I solved the problem by running the follow commands for the affected tables/sequences.
Specifically running the command:
manage.py dbshell
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
change tablename_colname_seq and tablename.colname
Don't let us guess and add the Error message to your question, this gives most information about where it fails.
Have you imported the User model?
from django.contrib.auth.models import User
I've had this problem as well and the only thing I could do was make the M2M fields blank and not set them until I hit Save and Continue Editing.
I think this just may be a framework wart, as you will notice the User section of the Admin site also has a very strict "You can only edit these fields until you save the model".
So my recommendation is to adopt that scheme, and hide the M2M form field until the model has a Primary Key.
I tried Django 1.3 using CPython, with different database setups. I copy-pasted the models from the question, and did some changes: first I added
from django.contrib.auth.models import User
at the top of the file and I put the reference to Tag between quotes. That shouldn't make any difference. Further, I created the following admin.py:
from django.contrib import admin
import models
admin.site.register(models.Tag)
admin.site.register(models.TogglDetails)
For Sqlite3, the problem described doesn't occur, neither for MySQL. So I tried PostgreSQL, with the postgresql_psycopg2 back end. Same thing: I can't reproduce the error.
So as far as I can figure, there's nothing wrong with the code in the question. The problem must be elsewhere.
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
When it comes to extending the User model, the above article list two methods: the old way (ForeignKey) and the new way (User model with inheritance). But at the same time, this article dates back to Aug 2008.
I am using Django's development version.
Would you recommend Extending the Django User model with inheritance or by using ForeignKey?
I read in a couple of posts that extending django.contrib.auth.models.User is not recommended, so I will not be looking at that.
AFAIK, the cleaner approach - if this can fit in your project architecture - is to have a distinct user profile model, and use the AUTH_PROFILE_MODEL setting to link it up to the Django User model.
See the Django Doc about storing additional information for Users
Dominique Guardiola is right. Use the AUTH_PROFILE_MODEL. James Bennett reiterated this in his 'Django in Depth' talk. http://www.youtube.com/watch?v=t_ziKY1ayCo&feature=related around 1hr:37mins.
Decide on the application where we want to house our user's profile, let's call it BngGangOfFour.
Define a Model class, lets name it UserProfile for clarity, and give it the extra field(s) we desire.
BngGangOfFour/models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User) #notice it must contain a 1 to 1 field with the auth user.
last_ip_address = models.CharField(max_length=20, default="")
Edit settings.py to designate our newly created model as the user profile.
settings.py
....
AUTH_PROFILE_MODULE = 'BngGangOfFour.UserProfile' #not case sensitive.
....
Access the profile directly off the user objects.
BngGangOfFour/views.py
....
def index(request):
if request.user.get_profile().last_ip_address = "127.0.0.1":
print("why hello me!")
return render_to_response('index.html', locals(), context_instance=RequestContext(request))
Sip a cold beer and call it a day.
The only time you can cleanly get away with extending User via inheritance is if you're writing an auth backend which will return an instance of the appropriate model instead.