Django admin page outside admin - django

This might be a simple Django question, but I hope I can get som advice. The following code in admin.py
class ExarbeteMomentInline(admin.TabularInline):
model = ExarbeteMoment
extra=0
class ExarbeteStudent(admin.TabularInline):
model = ExarbeteStudent
extra=0
class ExamensarbeteAdmin(admin.ModelAdmin):
list_display = ('title', 'start_date', 'end_date', 'company')
inlines = [ExarbeteMomentInline, ExarbeteStudent]
admin.site.register(Examensarbete,ExamensarbeteAdmin)
produces what I want, in the admin panel.
But I want a version of it outside the admin panel, so that regular users can enter data. How can I modify the code in a minimal way to get essentially the same page outside the admin region?
Thanks, in advance.
/ADDED/
My models are:
class Examensarbete(models.Model):
title = models.CharField(max_length=10000,default='',blank=True)
start_date = models.DateField('startdatum')
end_date = models.DateField('slutdatum',blank=True,default='',null=True)
company = models.CharField(max_length=200,default='',blank=True)
comment = models.TextField(max_length=1000,default='',blank=True)
kurskod = models.CharField(max_length=100,default='FMAM05')
year = models.CharField(max_length=5,blank=True,default='',null=True)
class ExarbeteMoment(models.Model):
exarbete = models.ForeignKey(Examensarbete,on_delete=models.CASCADE)
typ = models.CharField(max_length=100)
person = models.ForeignKey(Personal,on_delete=models.SET_NULL,null=True)
tim = models.FloatField(null=True)
class ExarbeteStudent(models.Model):
exarbete = models.ForeignKey(Examensarbete,on_delete=models.CASCADE)
first_name=models.CharField(max_length=100)
last_name=models.CharField(max_length=100)
pnr = models.CharField(max_length=13)
program = models.CharField(max_length=5)
kull = models.CharField(max_length=5)
where I have deleted str and Meta. I guess I should be able to solve the problem with the help below, but I can't still figure out how I get what I get in the admin panel, with Examensarbete above and then two subforms with ExarbeteMoment and ExarbeteStudent. And the 'add another item' feature.
Unfortunately I am new to Django, and find it particularly hard to work with forms and formsets. I am not quite sure why, because they should simplify things considerably.

I agree with the comment from Roman Kovalevsky - you will need to write the functions by yourself. Django however supports you with forms and formsets to do this job. As you did not post your models in the question i can only show you an example with some random named variables:
class ExarbeteStudent(forms.Form):
description = forms.CharField(widget=AdminTextareaWidget)
date1 = forms.DateField(widget=AdminDateWidget)
date2 = forms.DateField(widget=AdminDateWidget)
task_list = Task.objects.all()
then you create a formset for the inline models as following
ExarbeteStudentFormSet = forms.formset_factory(ExarbeteStudent,
extra=1,
max_num=60,
can_delete=True,
Here you find some more informations about forms and formsets
https://docs.djangoproject.com/en/2.0/topics/forms/formsets/

Related

django admin edit model select/prefetch_related?

I have a Django website, with model Event, lets say:
class Event(models.Model):
home = models.ForeignKey('Team', related_name='%(class)s_home')
away = models.ForeignKey('Team', related_name='%(class)s_away')
...
class Team(models.Model):
name = models.CharField("team's name", max_length=100)
Using ForeignKeys for this was a bad idea, but anyway, how to make this usable in Django Admin page?
In admin edit event page, a ton of foreign keys is fetched for this:
http://127.0.0.1:8000/admin/event/event/116255/
It produces tons of selects like:
SELECT "event_team"."id", "event_team"."name" FROM "event_team" WHERE "event_team"."id" = 346;
and page dies. I was playing with these:
class EventAdmin(admin.ModelAdmin):
list_display = ('id', 'home', 'away', 'date_game', 'sport', 'result')
search_fields = ['home__name', 'away__name']
list_select_related = (
'home', 'away', 'league', 'sport', ...
)
def get_queryset(self, request):
return super(EventAdmin, self).get_queryset(request).select_related(*self.list_select_related)
admin.site.register(Event, EventAdmin)
But no luck.
The simplest, quickest way
It would be to add raw_id_fields on your ModelAdmin (Django ModelAdmin.raw_id_fields documentation) :
class EventAdmin(admin.ModelAdmin):
raw_id_fields = ("home", "away")
It would result in a inputText with the FK field ids in such as :
.
Loading will be fast as it won't populate a select list with ALL the teams.
You'll have the Django admin change_view of the Team ModelAdmin to select the teams, thanks to the browse icon.
A nicer way ?
A lot more elegant on the UX side of things, it requires you to know part of the name of the team: using an ajax autocomplete widget to represent your field.
You could use for example Django Autocomplete Light (DAL) quick tutorial by having a custom form for your admin and a autocompleteModelSelect2 for your home and away fields (with 2 differents QS in the ajax view).
It will produce a field looking like:
.
The tutorial of this link have all you need!
Or you can chose another third party plugin or build your own field/widget to produce a similar result.
I think #ppython's answer is the simplest and works perfectly but I ended up using autocomplete_fields instead of raw_id_fields. Achieving a more friendly approach, it has been available since Django 2.0.
Following the answer, it'll be something like this:
class EventAdmin(admin.ModelAdmin):
autocomplete_fields = ['home', 'away']
I found the problem, it was my mistake and I did not even mention it in question :(
So this is my model, but I did not mention important part if it:
class Event(models.Model):
home = models.ForeignKey('Team', related_name='%(class)s_home')
away = models.ForeignKey('Team', related_name='%(class)s_away')
merged = models.ForeignKey('Event', null='True', blank='True')
def __unicode__(self):
return str(self.id) + ": " + self.home.name + " - " + self.away.name
Problem was not with home or away, but with merged field, that fetched self.home.name and self.away.name for each event.
Replaced with
def __unicode__(self):
return 'Event id: {}'.format(self.id)
and added merged to list_select_related
fixed my problem. Thanks for help and sorry for incomplete question.

Preventing Django admin panel to show drop-down list in Inline display of ManyToMany relationships

I have a self-referencing model in Django 1.5 as shown below:
RELATIONSHIP_PARENT = 1
RELATIONSHIP_BLOCKED = 2
RELATIONSHIP_STATUSES = (
(RELATIONSHIP_PARENT, 'Parent'),
(RELATIONSHIP_BLOCKED, 'Blocked'),
)
class Message(models.Model):
content = models.CharField("Content", max_length=160, db_index=True)
relationships = models.ManyToManyField('self',
through='Relationship',
symmetrical=False,
related_name='related_to')
class Relationship(models.Model):
parent_message = models.ForeignKey(Message, related_name='parent_messages')
child_message = models.ForeignKey(Message, related_name='child_messages')
status = models.IntegerField(choices=RELATIONSHIP_STATUSES)
And I configured Django admin to show me Relationships as inline when viewing individual Message panel as below:
from django.contrib import admin
from demo.models import Message, Relationship
class RelationshipInline(admin.TabularInline):
model = Relationship
extra = 0
fk_name = 'parent_message'
class MessageAdmin(admin.ModelAdmin):
inlines = (RelationshipInline,)
admin.site.register(Message, MessageAdmin)
admin.site.register(Relationship)
I intend to store many messages (with a lot of parent-child connections among them) in the table. Whenever I view individual message via Admin panel, I see something like this:
As shown in the red circle, Django admin collects all messages in the database and display them as drop-down list in the menu. I have read through a few ways to prevent it and the closest that I found is Representing ManyToMany relation in the Admin Panel but when I tried putting raw_id_fields = ('parent_message', ) under RelationshipInline class, it doesn't seem to do anything.
If anyone can recommend me to a link or resource or just show me how to prevent Django from showing every entry/messages in the drop-down list, I would greatly appreciate the help. Thank you.
This should work.
class RelationshipFormSet(BaseInlineFormSet):
def get_queryset(self):
if not hasattr(self, '_queryset'):
criteria = {} #Your criteria here
qs = super(RelationshipFormSet, self).get_queryset().filter(**criteria)
self._queryset = qs
return self._queryset
class RelationshipInline(admin.TabularInline):
model = Relationship
extra = 0
fk_name = 'parent_message'
formset = RelationshipFormSet
The raw_id_fields should go in the admin class:
admin.py
class MessageAdmin(admin.ModelAdmin):
inlines = (RelationshipInline,)
raw_id_fields = ('parent_message', )

Jython Django1.3 admin panel pagination does not seem to work

i have a basic django-jython aplication which i am using admin panel on it, and it seems even if i declare the 'list_per_page = 25' in my admin.py for each modeladmin class, it cant paginate the results. i have a table that contains 900.000 rows and django is trying to put all the rows in a one page. when i declare the 'list_per_page' option, it puts page numbers and total count of data below the page but then puts all the rows in every page. i know it sounds strange but i cant find any solution. Here is my Model class also here is my ModelAdmin code sample :
class MahalleAdmin ( admin.ModelAdmin ):
list_display = ('KOD','AD','TIP','YETKILIIDAREKODU','KOYKODU')
list_filter = ['AD','TIP','YETKILIIDAREKODU','KOYKODU']
search_fields = ['KOD','AD','TIP','YETKILIIDAREKODU','KOYKODU']
paginator = paginator.Paginator
list_per_page = 25
class MAHALLE_MERSIN ( models.Model ):
class Meta:
db_table = 'MAHALLE_MERSIN'
verbose_name = 'MERSİN MAHALLELERİ'.decode('Latin5')
verbose_name_plural = 'MERSİN MAHALLELERİ'.decode('Latin5')
#app_label = 'MESKİ ERP'.decode('Latin5')
def __unicode__(self):
return self.AD
KOD = models.AutoField(primary_key = True)
AD = models.CharField( max_length=512)
TANITIMKODU = models.IntegerField()
TIP = models.ForeignKey(MAHALLE_TIP ,db_column= 'TIP')
YETKILIIDAREKODU = models.ForeignKey( KURUM , db_column='YETKILIIDAREKODU')
KOYKODU = models.ForeignKey(KOY_MERSIN ,db_column= 'KOYKODU')
My guess is that you are running with the Django-Jython Oracle driver (doj.backends.zxjdbc.oracle), am I right? There is an issue with pagination in Oracle that I logged with the developer. It seems to be a problem only with the Oracle implementation of doj, the MySQL driver works fine.
Oracle Pagination in Admin interface
I really need to get this working for a project, so I'm gonna try to fix it myself and submit a patch. I will update you if/when it is fixed.

Viewing subset of objects in Django, Views, URLs, Models

I know this is a very basic concept in Django, and I have tried the tutorial but it is not working. I am working on a comic book database with the models set like this (at least, a sample of two of the models):
Class Title(models.Model):
title = models.CharField(max_length=256)
vol = models.IntegerField("Vol.")
slug = models.SlugField(blank=True, null=True)
#desc = models.CharField(max_length=256)
class Meta:
ordering = ['title']
def get_absolute_url(self):
return "/comics2/title/%s" % self.slug
def __unicode__(self):
return self.title
class Issue(models.Model):
title = models.ForeignKey(Title)
number = models.IntegerField(help_text="Enter the number only. Do not include the hashtag.")
writer = models.ManyToManyField(Creator)
What I am trying to do is create a page that shows a list of all the issues within that Title.
But, I have it setup in the views like this:
class AstonishingXMenIssueListView(ListView):
context_object_name = "astonishing_list"
queryset = Issue.objects.filter(title__title="Astonishing X-Men").order_by("number")
template_name = "comics2/astonishing_list.html"
My urls.py look like this:
(r'^comics2/title/(?P<title_slug>[-\w]+)/$', AstonishingXMenIssueListView.as_view(
)),
Of course, going to /uncanny-xmen-v1/ shows the same thing as the Astonishing link above.
Obviously, this is not a practical way to list issues by title for future issues and titles, so I need it setup so that I don't have to individually do this. Now, I have tried following the Django generic views tutorial, but I got an index tuple error.
I've tried this, but it doesn't work. This is what gets me the index tuple error.
class IssuesByTitleView(ListView):
context_object_name = "issues_by_title_list"
template_name = "comics2/issues_by_title.html",
def get_queryset(self):
title = get_object_or_404(Title, title__iexact=self.args[0])
return Issue.objects.filter(title=title)
Any ideas? And can someone please reply in baby-language, as I am new to Django and Python, so simply telling me to look at the Tutorial again isn't going to help. So, maybe writing out the code would help! Thanks!
Generally, your IssueByTitleView is the right way to do it. But as you use named groups in your URL regex (the (?P<title_slug>[-\w]+) part of your URL), you have to access the URL parameters through self.kwargs instead of self.args. Also, you have to filter on the slug field, not the title field:
title = get_object_or_404(Title, slug=self.kwargs['title_slug'])

How to get logged-in user info in Django's forms.py

I have created a Profile model including the Gender info. There is also models called Dorm and Registration (not used for user registration) like this:
class Registration(models.Model):
user = models.ForeignKey(User)
pref1 = models.ForeignKey(Dorm, related_name="pref1",verbose_name=u"Preference 1",null=True)
...
friend1 = models.CharField(u"Friend 1", max_length=15,blank=True)
class Dorm(models.Model):
name = models.ForeignKey(Building)
gender = models.CharField(u"Gender", max_length=1, blank=True, choices=GENDER_CHOICES)
Now, i am trying to generate a form for this Registration model with forms.ModelForm like this:
class RegistrationForm(forms.ModelForm):
dorms = Dorm.objects.filter(gender='M')
pref1 = forms.ModelChoiceField(queryset=dorms, empty_label=None)
...
class Meta:
model = Registration
exclude = ('user')
as you can see in the second line, i am querying the dorms with a hardcoded gender value M. Instead of the hardcoded value, I need to get the users' gender, and query the database with that gender information.
I have been searching the documentation but I could not find anything. Can you help me? How can I learn the logged-in User' profile information in Django Forms?
So without using some sort of monkeying around of the init function a "form_factory" is probably the best approach.
def RegFormFactory(user)
dorms = Form.objects.filter(gender = "user.gender")
class _RegistrationForm(forms.ModelForm):
pref1 = forms.ModelChoiceField(queryset = dorms, empty_label=None)
class Meta:
model = Registration
exclude = ('user')
return _RegistrationForm
then use:
formclass = RegFormFactory(user)
form_inst = formclass()
...
form_inst = formclass(request.POST)
This is described very nicely in a blog post here: So you want a dynamic form.
James Bennett wrote a blog post that should explain perfectly what you need: So you want a dynamic form