I have a django application in which I want to use model inheritance. The application contains one super model class Article and here is its code
class Article(models.Model):
english_title = CharField(max_length=200)
arabic_title = CharField(max_length=200)
english_body = HTMLField()
arabic_body = HTMLField()
enabled = BooleanField()
def __unicode__(self):
return self.english_title
def get_body(self, locale):
if locale == "ar" :
return self.arabic_body
else:
return self.english_body
def get_title(self, locale):
if locale == "ar" :
return self.arabic_title
else:
return self.english_title
and there is a child class called History which extends this class and here is its code
class History(Article, IHasAttachments):
date = DateField(auto_now_add=True)
My problem appears in the admin application where the dateField (date) in the History model does not appear in the admin form when inserting new entry.
NOTE: I am using django-tinymce, djnago-filebrowser, and django-grappelli
What would be the problem?
I think the problem is in your History model you set auto_now_add=True, which will prevent your date field shown on admin, please check the django document about Model field reference:
As currently implemented, setting auto_now or auto_now_add to True will cause the field to have editable=False and blank=True set.
And about Field.editable:
If False, the field will not be displayed in the admin or any other ModelForm.
If you want it editable but also has a default value, try this:
class History(Article, IHasAttachments):
date = DateField(default=datetime.date.today)
Perhaps its inheritance problem, try with mixing:
http://www.linuxjournal.com/node/4540/print
If you add auto_now=True this field will be update at every modification. So it will logically normal you couldn't edit it.
If you want to add automatic date when you create an instance, I suggest you this:
from django.utils.timezone import now
class History(Article, IHasAttachments):
date = DateField(default=now())
Related
I'm new to django and trying to do something with an issue.I have this model:
class MyModel(models.Model):
value = models.CharField(max_length=50, choises=...)
custom_value = models.CharField(max_length=50, blank=True)
And I need custom_value field to be enabled to edit only if value of value field is "CUSTOM".
I'm assuming when you say 'enabled to edit' you are referring to a form field.
I'm also assuming that the data will already be saved in the model when the form loads.
In that case, this should be done on the corresponding Form for that model. You'll need to initialize that form field to be disabled, and then enable it on the form load.
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
custom_value = self.fields.get('custom_value')
if custom_value and custom_value.widget.attrs['value'] == 'CUSTOM':
self.fields['value'].widget.attrs['disabled'] = 'false'
I know your code is just an example, but using value as class attribute name is confusing.
If you were hoping to do this dynamically on one form, as in having a user select a choice and then see another option become enabled without a browser refresh, that must be done in Javascript. This is how you would do it with just Django forms.
There are similar questions to this, but I believe mine is different. I am very new to Django and to Python, so please forgive my ignorance.
I have a custom class UserProfile that inherits from the django.contrib.auth.models User class. This UserProfile is based on the exercise in Tango with Django, however, I am using the example to create a different project/app.
I have UserProfile linked to the standard User model with a OneToOneField relationship in my models.py, as shown below:
class UserProfile(models.Model):
# Links UserProfile to a User model instance.
user = models.OneToOneField(User)
# The additional attribute I wish to include that isn't in User.
slug = models.SlugField(unique=True)
In my admin.py file, I want an interface for UserProfile that I can work with, and I want the slugfield to autopopulate when I enter a new UserProfile. I want it to autopopulate based on the username attribute of User. However, I can't seem to make it work. Here is my admin.py code:
class UserProfileAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("user.username",)}
When I try to runserver from my command line, I get the following error:
ERRORS: <class 'climbcast.admin.UserProfileAdmin'>: (admin.E030) The
value of >'prepopula ted_fields["slug"][0]' refers to 'user.username',
which is not an attribute of >' climbcast.UserProfile'.
System check identified 1 issue (0 silenced).
It won't allow me to access the user.username attribute this way, even though I can access it that way in the python shell. Any ideas on how to make this work?
Unfortunately prepopulated_fields doesn’t accept DateTimeField, ForeignKey, nor ManyToManyField fields.
Source: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.prepopulated_fields
Possible solution, in your models.py (make slug attribute optional):
from django.utils.encoding import force_text
from django.template.defaultfilters import slugify
class UserProfile(models.Model):
[...]
slug = models.SlugField(blank=True, db_index=True, unique=True)
def get_unique_slug(self, value):
"""
Generate a valid slug for a for given string.
"""
qs = self.__class__.objects.all()
used = qs.values_list('slug', flat=True)
i = 1
baseslug = slugify(value)
while slug in used:
slug = '%s-%s' % (baseslug, i)
i += 1
return slug
def save(self, *args, **kwargs):
if not self.slug and self.user:
self.slug = self.get_unique_slug(force_text(self.user.username))
super(UserProfile, self).save(*args, **kwargs)
I am relatively new to Django and I'm trying to achieve something that is not quite clear in the documentation. My application requires multiple types of users. So, I have extended django User, creating a Profile model that contains additional fields common in all User types:
USER_TYPES = (
('A', 'UserTypeA'),
('B', 'UserTypeB'),
('C', 'UserTypeC'),
)
class Profile(models.Model):
user = models.OneToOneField(User, unique=True)
about = models.TextField(blank=True)
user_type = models.CharField(max_length=3, choices=USER_TYPES, default='A')
def save(self, *args, **kwargs):
try:
existing = Profile.objects.get(user=self.user)
self.id = existing.id #force update instead of insert
except Profile.DoesNotExist:
print "Profile not created yet"
models.Model.save(self, *args, **kwargs)
def create_user(sender, instance, created, **kwargs):
print "User Profile Creation: False"
if created:
print "User Profile Creation: ", created
Profile.objects.create(user=instance)
post_save.connect(create_user, sender=Profile)
In settings.py I have set:
AUTH_PROFILE_MODULE = 'users.Profile'
After that i have defined my UserTypeX models deriving from Profile models like this:
class UserTypeA(Profile):
phone_number = models.CharField(max_length=13,blank=False)
class UserTypeB(Profile):
company_name = models.CharField(max_length=30,blank=False)
phone_number = models.CharField(max_length=13,blank=False)
def __init__(self, *args, **kwargs):
kwargs['user_type'] = 'B'
super(UserTypeB, self).__init__(*args, **kwargs)
...
I've registered those user models to admin so that I could manage my users independently.
The default admin behavior displays correctly all the Profile and UserTypeX fields and there is a select box (with a plus button next to it) for the User field - due to the OneToOneField relationship between Profile and User models. So whenever I want to create a new UserTypeX, I have to press the plus button and fill in a new popup window all the default User django defined fields.
What I am struggling to do now is display those User fields, not in a new popup window but inline in my UserTypeX add/edit page. I've read the documentation about StackedInlines and TabularInlines but those doesn't fit my case because I want to inline parent fields in an ancestor's add/edit page and not vice versa.
Is there any suggested solution with example code (please!) for that problem? Thank's in advance!
So, to make things short, is there a way to display User fields (instead of the select/add functionality due to OneToOneField relationship) in Profile add/edit screen in admin?
Update: A related question (unanswered though...) that briefly addresses the problem is:
Reverse Inlines in Django Admin
No, you cannot. But you can make B inline in A if you want. Or maybe you can manipulate how django display it in
def unicode(self):
models.py
class A(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class B(models.Model):
name = models.CharField(max_length=50)
a = models.ForeignKey(A)
admin.py
class B_Inline(admin.TabularInline):
model = B
class A_Admin(admin.ModelAdmin):
inlines = [
B_Inline,
]
admin.site.register(A, A_Admin)
admin.site.register(B)
Or maybe you want to use many-to-many relationship?
models.py
class C(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class D(models.Model):
name = models.CharField(max_length=50)
cs = models.ManyToManyField(C)
admin.py
class C_Inline(admin.TabularInline):
model = D.cs.through
class D_Admin(admin.ModelAdmin):
exclude = ("cs",)
inlines = [
C_Inline,
]
admin.site.register(C)
admin.site.register(D, D_Admin)
I don't see how this is going to work - you have told django to use users.Profile as your profile model but you actually want to use it's children. Plus as you say you're wanting to use the inline forms the "wrong way around". Without knowing more about what exactly you're trying to achieve I'd suggest that you could fix the inline form issue by defining a custom view to edit the user details rather than using django admin. As for the different profile types - I'd suggest just defining a profile type field in the model and then hiding/showing different fields/properties depending on its value
I have a ForeignKey field in a model of mine, and I'm using ModelForm with it to generate the HTML. The thing is, I want to add an Other option as well - I plan to add JavaScript with it so that a textbook appears when that's selected.
I'm looking at http://docs.djangoproject.com/en/1.2/topics/forms/modelforms/#overriding-the-default-field-types-or-widgets, and started off with trying something like
class Event(models.Model):
name = models.CharField(max_length=200)
time = models.DateField()
.
.
.
cost = models.CharField(max_length=200)
affiliation = models.ForeignKey('Affiliation')
def __unicode__(self):
return self.name
class EventForm(ModelForm):
cost = models.TextField()
class Meta:
model = Event
cost should become a text field instead of char field, so the output should be textarea instead of input[type=text]. This doesn't change, however, no errors are printed, and nothing really happens. I was hoping to proceed by doing
class EventForm(ModelForm):
affiliations = list(Affiliation.objects.all()).append('Other')
affiliation = forms.CharField(choices=affiliations)
class Meta:
model = Event
I'm using django-nonrel on GAE if it helps, but this isn't really an issue with the Model (or so I think...) so I don't think it should change anything. Any help would be much appreciated!
I haven't used django-nonrel, so take this tip with a grain of salt (YMMV).
In your EventForm definition, you're setting cost to be a model.TextField - but you actually want it to be a forms.CharField, with a textarea widget.
Your problem is that EventForm is overriding cost with a models.TextField() when it should be forms.CharField(widget=forms.Textarea())
Can a CharField have choices? Django docs show a 'ChoiceField' which would seem to be what you want...
http://docs.djangoproject.com/en/1.2/ref/forms/fields/#charfield
I'm having trouble doing an aggregation query on a many-to-many related field.
Here are my models:
class SortedTagManager(models.Manager):
use_for_related_fields = True
def get_query_set(self):
orig_query_set = super(SortedTagManager, self).get_query_set()
# FIXME `used` is wrongly counted
return orig_query_set.distinct().annotate(
used=models.Count('users')).order_by('-used')
class Tag(models.Model):
content = models.CharField(max_length=32, unique=True)
creator = models.ForeignKey(User, related_name='tags_i_created')
users = models.ManyToManyField(User, through='TaggedNote',
related_name='tags_i_used')
objects_sorted_by_used = SortedTagManager()
class TaggedNote(models.Model):
"""Association table of both (Tag , Note) and (Tag, User)"""
note = models.ForeignKey(Note) # Note is what's tagged in my app
tag = models.ForeignKey(Tag)
tagged_by = models.ForeignKey(User)
class Meta:
unique_together = (('note', 'tag'),)
However, the value of the aggregated field used is only correct when the model is queried directly:
for t in Tag.objects.all(): print t.used # this works correctly
for t in user.tags_i_used.all(): print t.used #prints n^2 when it should give n
Would you please tell me what's wrong with it? Thanks in advance.
I have figured out what's wrong and how to fix it now :)
As stated in the Django doc:
Django interprets the first Manager defined in a class as the "default" Manager, and several parts of Django will use that Manager exclusively for that model.
In my case, I should make sure that SortedTagManager is the first Manager defined.
2.I should have count notes instead of users:
Count('notes', distinct=True)