Add custom field to admin fields - django

models.py
class Video(models.Model ):
embedded_code = models.TextField(blank=False, null=False, default='')
This field represents youtube's embedded code.
In the form for editing an instance I'd like to have a link to a detail view where I would like to show the video. In other words, I don't want to shoow the video in the admin site, I'd like just to create a link. And it is not about list_display.
For that purpose in the model I could organise something like that:
def preview(self):
href = reverse('vocabulary-videos:detail', kwargs={'pk': self.id})
a = "<a href='{}'>Preview</a>".format(href)
return mark_safe(a)
Is it possible to show this link in the edit form without substituting the template?

Related

Adding relation to object with preview or something like this

I have Document model:
class Document(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=255)
description = models.TextField()
content = models.TextField()
and DocumentRelation model:
class DocumentRelation(models.Model):
document_a = models.ForeignKey(Document,related_name='doc_a')
document_b = models.ForeignKey(Document,related_name='doc_b')
I have single_document views:
def single_document(request,id):
doc = Document.objects.get(id=id)
return render_to_response('single_file.html',{'doc':doc},context_instance=RequestContext(request))
In single_file.html I have:
Add related document
I need create views def add_relation(request,id):. What is the best way to add the relationship? I need a preview of the document that to be added as related. How to solve it?
(I ask about the overall design. How to solve it)
First, why are you not using a ManyToManyField in the document model like this :
related_documents = models.ManyToManyField('self')
Then you can use a two steps form if you do not want to use javascript (one to select, another to confirm and display the related document).
If you want, you can also use javascript and dynamically load the related document when the user select it.

Form within a form in Django?

I have been looking at the documentation and thought maybe inline-formsets would be the answer. But I am not entirely sure.
Usually whenever you create a ModelForm it is bound to the related Model only. But what if you wanted to edit two models within a form?
In a nutshell, when editing the class conversation, and selecting a Deal class from the dropdown, I would like to be able to change the status of the selected deal class as well (but not the deal_name). All within the same form. Does Django allow that?
class Deal(models.Model):
deal_name = models.CharField()
status = models.ForeignKey(DealStatus)
class Conversation(models.Model):
subject = models.CharField()
deal = models.ForeignKey(Deal, blank=True, null=True)
Update:
The reason I wasn't sure if inline-formssets are the answer is the following behaviour:
View:
call = get_object_or_404(contact.conversation_set.all(), pk=call_id)
ConversationFormSet = inlineformset_factory(Deal, Conversation)
fset = ConversationFormSet(instance=call)
variables = RequestContext(request, {'formset':fset})
return render_to_response('conversation.html', variables)
Template
{{ formset }}
The result I am getting is not what I expected. I am getting three forms of Conversation class, where the first one is filled out (due editing and passing in the isntance). However the Deal DropDown menu is not listed at all. Why?
I found the solution and hope this will help someone else with the same problem in the future. I ended up redesigning my models.
I simply added the status also to my Conversation model.
class Conversation(models.Model):
subject = models.CharField()
deal = models.ForeignKey(Deal, blank=True, null=True)
status = models.ForeignKey(DealStatus)
In the view I added a custom save like this:
if form.is_valid():
call = form.save(commit=False)
deal = get_object_or_404(Deal.objects.all(), pk=call.deal.id)
deal.status = call.status
deal.save()
call.save()
That works nicely.
Another approach is to use signal like this:
def update_deal_status(sender, instance, created, **kwargs):
if created:
deal = Deal.objects.get(id__exact=instance.deal_id)
deal.status = instance.status
deal.save()
signals.post_save.connect(update_deal_status, sender=Conversation)

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'])

Referencing a Django contrib.admin user via a foreign key?

I'm developing a small Django site and I'm using django.contrib.admin to handle content management. I'd like to capture the first name & last name of the author (an Admin user) of an Article on its initial save (and not update it if another user edits the Article).
ie.
class Article(models.Model)
title = models.CharField(max_length=50)
pub_date = models.DateTimeField('date published')
author = ForeignKey(???)
...
What do I need to write to grab this user's first name & last name fields when creating a new Article object? I'd default to their admin username if those fields are blank.
Have your model use the User object:
author = models.ForeignKey(User)
To prevent this field from being changeable on update, check out this other SO post:
Django admin: exclude field on change form only
To change the admin's Select field to use first/last name, you could try this snippet:
http://djangosnippets.org/snippets/1642/
To change the admin's view, assuming you are using the built-in templates, you could add a custom column as described on this post: How do I add a custom column with a hyperlink in the django admin interface?
class AuthorAdmin(admin.ModelAdmin):
list_display = ('author_name',)
def my_author_name(self, obj):
if obj.author.first_name and obj.author.last_name:
return '%s %s' % (obj.author.first_name, obj.author.last_name)
else:
return obj.author.username
my_author_name.allow_tags = True
my_author_name.short_description = 'Author'
I think you are looking for this:
author = models.ForeignKey(User)
It looks like the best way to handle a None or blank result from get_full_name is to just populate User.author with models.ForeignKey(User) and then — at the template level — use the following:
{{ user.get_full_name|default:user.username }}
... via this SO answer. This allows me to perform queries on a User's Articles, but still gracefully handles blank first_name & last_name fields if a User hasn't entered them yet, but will also update dynamically when they have).

How to access model data when overriding Django admin templates?

sorry if this is an obvious question but I have been searching for a few days and have not been able to come up with a result.
I am creating a simple photo gallery app. There are four galleries, each containing a photo (the photo consists of a 'before' image, 'after' image and caption). I am trying to use django-admin to allow users to click on a gallery and then add photos.
I am using a TabularInline to edit the photos within each gallery. In addition to the default columns on the TabularInline, I would like to add a column that shows a thumbnail preview of the 'before' photo and 'after' photo (I am using easy-thumbnails for this). After much searching, it seems like the best way to do this is to override the django-admin tabularInline.html template and add the column myself - so I created another copy and am trying to edit it now.
What I would like to do is simply reference the Photo object within the Django admin template that I am overriding - but I don't know the appropriate tag to use. I need the reference so I can use it in conjunction with the easy-thumbnails thumbnail tag ... but for the life of me I cannot figure out the template tag that references the object. I have tried iterating through the ModelForm, FormSet, and FieldSet objects but none seem to give me a direct reference to the object.
# models.py
class Gallery(models.Model):
name = models.CharField(max_length=200)
url = models.CharField(max_length=200)
desc = models.TextField()
def __unicode__(self):
return self.name
class Photo(models.Model):
gallery = models.ForeignKey(Gallery)
before = models.ImageField(upload_to='gallery')
after = models.ImageField(upload_to='gallery')
caption = models.CharField(max_length=1000)
order = models.IntegerField(blank = True, null = True)
def __unicode__(self):
return "Photo " + str(self.order)
# admin.py
class GalleryForm(forms.ModelForm):
model = Gallery
class Media:
js = (
'/assets/js/jquery-1.4.2.min.js',
'/assets/js/jquery-ui-1.8.2.custom.min-admin-sortable.js',
'/assets/js/menu-sort.js',
)
class PhotoInline(admin.TabularInline):
model = Photo
extra = 1
template = "admin/tabular-thumbnails.html"
admin.site.register(Gallery,
inlines=[PhotoInline],
form = GalleryForm)
Thanks so much in advance and please let me know if there's any additional information I can offer. I am using Django 1.1
In Django 2.1 {{adminform.form.instance.field_name}} worked for me.
{{ form.instance }} will always be the model instance associated with a modelform, assuming there is one.
(Note that ``{{ formset.instance }}` is the instance of the parent model in an inline formset).