I'm trying to extend a Django class providing from external library in my view in order to add some things. It's the first time I'm doing this kind of thing and I need some help.
In my external module
I have this class named EdqmThreadCreateView :
class EdqmThreadCreateView(ForumPermissionMixin, ThreadCreateView):
def __init__(self):
super(EdqmThreadCreateView, self).__init__()
self.form_class.base_fields['body'].label = 'Message'
def get_initial(self):
"""
Returns the initial data to use for forms on this view.
"""
initial = self.initial.copy()
# Get default topic
topic_id = self.request.GET.get('topic', None)
if topic_id:
initial['topic'] = int(topic_id)
return initial
def form_valid(self, form):
""" Save form if it is valid """
thread = form.save(self.request.user)
url_redirect = get_absolute_url(thread)
return HttpResponseRedirect(url_redirect)
This class is in urls.py file of external module :
urlpatterns = [
url(r'^forum/new', EdqmThreadCreateView.as_view(), name='forum-create-thread'),
...
]
In my django app
I would like to use the previous code, but I would like to add some things : change the url, add variables, ...
In my views.py file, I wrote a very easy example to see if my class is called :
from edqm.forum.views import EdqmThreadCreateView
class KnowxThreadCreateView(EdqmThreadCreateView):
def form_valid(self, form):
print('this is the class used')
And urls.py file :
from .views import KnowxThreadCreateView
urlpatterns = [
url(r'^forum/new', KnowxThreadCreateView.as_view(), name='forum-create-thread'),
]
If I understand the inherit process, it should work right ? But where Django select the function which will be used if 2 classes called the same url ?
It's a bit unclear for me
Quite simply, you can't have two views using the same URL. If you need separate functionality provided by a separate view, define a separate URL.
According to django docs:
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = [
url(r'^my_view/$', self.my_view),
]
return my_urls + urls
def my_view(self, request):
# ...
context = dict(
# Include common variables for rendering the admin template.
self.admin_site.each_context(request),
# Anything else you want in the context...
key=value,
)
return TemplateResponse(request, "sometemplate.html", context)
If I am not wrong, we can do the same thing by adding url in urls.py and the views in views.py as it is normally done then, what is the use of introducing this way? I am a newbie to django and I may be missing something here.
Can you please provide an example where we cannot do it in views.py and we must use the above method?
Any guidance/help would be appreciated.
I think I figured out, both of them can be used to do the same thing but the key difference is that the views which you write using above method will belong to admin app while the general views in views.py belongs to the particular app in you have written.
Hence, the url in ModelAdmin need to be called using name admin:url_name since the url goes as admin/my_views/ in given example.
I am stuck with an automation problem in that I have a django project with multiple subdomains, one for each council model instance. All of my models have a foreignfield of 'council' and that is how I am filtering the context of the sites by creating a separate view for each council that I add.
However I would like to somehow create a way to automate adding a view class with the right filtered context each time I add a model instance (Council).
Also I will need to add another url in the urlpatterns which again I am stumped maybe a bit of python could help there but the views are my main concern.
in my views:
class RedmarleyPageView(TemplateView):
template_name = "index.html"
def get_context_data(self, **kwargs):
council_no = 1
context = super (RedmarleyPageView, self).get_context_data (**kwargs)
context['members'] = Member.objects.filter (council=council_no)
context['roles'] = Role.objects.filter (council=council_no)
context['minutes'] = Minute.objects.filter (council=council_no)
context['agendas'] = Agenda.objects.filter (council=council_no)
context['documents'] = Document.objects.filter (council=council_no)
context['articles'] = Article.objects.filter (council=council_no)
context['councils'] = Council.objects.filter (id=council_no)
context['settings'] = Setting.objects.filter(council=council_no)
context['events'] = Event.objects.filter(council=council_no)
context['eventscategories'] = EventCategory.objects.all()
return context
urls:
url(r'^$', HomePageView.as_view(), name='home'),
url(r'^redmarley/', RedmarleyPageView.as_view(), name='redmarley'),
Redmarley in this context is the council inst. and I need it to be able to create a view and url like above for each instance.
I'm trying to add a custom page to the admin without a model association.
This is what I achieved so far.
class MyCustomAdmin(AdminSite):
def get_urls(self):
from django.conf.urls import url
urls = super(MyCustomAdmin, self).get_urls()
urls += [
url(r'^my_custom_view/$', self.admin_view(MyCustomView.as_view()))
]
return urls
class MyCustomView(View):
template_name = 'admin/myapp/views/my_custom_template.html'
def get(self, request):
return render(request, self.template_name, {})
def post(self, request):
# Do something
pass
admin_site = MyCustomAdmin()
admin_site.register(MyModel1)
admin_site.register(MyModel2)
# etc...
This is actually working but the problem is that with this solution I loose some apps from the Django admin interface (account, auth, socialaccounts, sites).
This is because your other admins are using the default admin.site. You need to totally replace the default admin.site with your own as explained here (you may also want to read this too).
Or you can just do it piggy-style by monkeypatching the default admin.site.get_urls() method:
from django.contrib import admin
_admin_site_get_urls = admin.site.get_urls
def get_urls():
from django.conf.urls import url
urls = _admin_site_get_urls()
urls += [
url(r'^my_custom_view/$',
admin.site.admin_view(MyCustomView.as_view()))
]
return urls
admin.site.get_urls = get_urls
Legal disclaimer : I won't be held responsible for any kind of any unwanted side-effect of this "solution", including (but not restricted too) your coworkers defenestrating you on the next code review. It's a dirty solution. It's a mess. It stinks. It's evil. You shouldn't do that, really.
I use django 1.7, python 2.7 I installed the search module vacancies vacancy created but maintaining job in the admin panel , there is an error .
NoReverseMatch at / ru / admin / careers / jobpost /
Reverse for 'jobpost_detail' with arguments' () 'and keyword arguments' {' slug ': u'67itut'} 'not found. 0 pattern (s) tried: [].
Already all pereprobaval
Models
from django.db import models
from django.utils.translation import ugettext_lazy as _
from mezzanine.conf import settings
from mezzanine.core.models import Displayable, RichText, Ownable
class JobPost(Displayable, RichText):
"""
A career job posting
"""
class Meta:
verbose_name = _("Job Post")
verbose_name_plural = _("Job Posts")
ordering = ("-publish_date",)
#models.permalink
def get_absolute_url(self):
url_name = "jobpost_detail"
kwargs = {"slug": self.slug}
return (url_name, (), kwargs)
def keyword_list(self):
return getattr(self, "_keywords", self.keywords.all())
Views
from calendar import month_name
from django.shortcuts import get_object_or_404
from collections import defaultdict
from django.contrib.contenttypes.models import ContentType
from django import VERSION
from careers.models import JobPost
from mezzanine.conf import settings
from mezzanine.generic.models import AssignedKeyword, Keyword
from mezzanine.utils.views import render, paginate
def jobpost_list(request, tag=None, year=None, month=None, template="careers/jobpost_list.html"):
"""
Display a list of job posts that are filtered by year, month.
"""
settings.use_editable()
templates = []
jobposts = JobPost.objects.published()
if tag is not None:
tag = get_object_or_404(Keyword, slug=tag)
jobposts = jobposts.filter(keywords__in=tag.assignments.all())
if year is not None:
jobposts = jobposts.filter(publish_date__year=year)
if month is not None:
jobposts = jobposts.filter(publish_date__month=month)
month = month_name[int(month)]
# We want to iterate keywords and categories for each blog post
# without triggering "num posts x 2" queries.
#
# For Django 1.3 we create dicts mapping blog post IDs to lists of
# categories and keywords, and assign these to attributes on each
# blog post. The Blog model then uses accessor methods to retrieve
# these attributes when assigned, which will fall back to the real
# related managers for Django 1.4 and higher, which will already
# have their data retrieved via prefetch_related.
jobposts = jobposts.select_related("user")
if VERSION >= (1, 4):
jobposts = jobposts.prefetch_related("keywords__keyword")
else:
if jobposts:
ids = ",".join([str(p.id) for p in jobposts])
keywords = defaultdict(list)
jobpost_type = ContentType.objects.get(app_label="careers", model="jobpost")
assigned = AssignedKeyword.objects.filter(jobpost__in=jobposts, content_type=jobpost_type).select_related("keyword")
for a in assigned:
keywords[a.object_pk].append(a.keyword)
for i, post in enumerate(jobposts):
setattr(jobposts[i], "_keywords", keywords[post.id])
jobposts = paginate(jobposts, request.GET.get("page", 1),
settings.CAREERS_PER_PAGE,
settings.MAX_PAGING_LINKS)
context = {"jobposts": jobposts, "year": year, "month": month, "tag": tag}
templates.append(template)
return render(request, templates, context)
def jobpost_detail(request, slug, year=None, month=None, day=None, template="careers/jobpost_detail.html"):
""". Custom templates are checked for using the name
``careers/jobpost_detail_XXX.html`` where ``XXX`` is the job
posts's slug.
"""
jobposts = JobPost.objects.published()
jobpost = get_object_or_404(jobposts, slug=slug)
context = {"jobpost": jobpost, "editable_obj": jobpost}
templates = [u"careers/jobpost_detail_%s.html" % unicode(slug), template]
return render(request, templates, context)
Urls
from django.conf.urls.defaults import patterns, url
# Job Post patterns.
urlpatterns = patterns("careers.views",
url("^tag/(?P<tag>.*)/$",
"jobpost_list",
name="jobpost_list_tag"),
url("^archive/(?P<year>\d{4})/(?P<month>\d{1,2})/$",
"jobpost_list",
name="jobpost_list_month"),
url("^archive/(?P<year>.*)/$",
"jobpost_list",
name="jobpost_list_year"),
url("^(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>.*)/$",
"jobpost_detail",
name="jobpost_detail_date"),
url("^(?P<slug>.*)/$",
"jobpost_detail",
name="jobpost_detail"),
url("^$",
"jobpost_list",
name="jobpost_list"),
)
Urls project
from __future__ import unicode_literals
from django.conf.urls import patterns, include, url
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin
from mezzanine.core.views import direct_to_template
admin.autodiscover()
# Add the urlpatterns for any custom Django applications here.
# You can also change the ``home`` view to add your own functionality
# to the project's homepage.
urlpatterns = i18n_patterns("",
# Change the admin prefix here to use an alternate URL for the
# admin interface, which would be marginally more secure.
("^admin/", include(admin.site.urls)),
)
urlpatterns += patterns('',
# We don't want to presume how your homepage works, so here are a
# few patterns you can use to set it up.
# HOMEPAGE AS STATIC TEMPLATE
# ---------------------------
# This pattern simply loads the index.html template. It isn't
# commented out like the others, so it's the default. You only need
# one homepage pattern, so if you use a different one, comment this
# one out.
url("^$", direct_to_template, {"template": "index.html"}, name="home"),
# HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
# ---------------------------------------------
# This pattern gives us a normal ``Page`` object, so that your
# homepage can be managed via the page tree in the admin. If you
# use this pattern, you'll need to create a page in the page tree,
# and specify its URL (in the Meta Data section) as "/", which
# is the value used below in the ``{"slug": "/"}`` part.
# Also note that the normal rule of adding a custom
# template per page with the template name using the page's slug
# doesn't apply here, since we can't have a template called
# "/.html" - so for this case, the template "pages/index.html"
# should be used if you want to customize the homepage's template.
# url("^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),
# HOMEPAGE FOR A BLOG-ONLY SITE
# -----------------------------
# This pattern points the homepage to the blog post listing page,
# and is useful for sites that are primarily blogs. If you use this
# pattern, you'll also need to set BLOG_SLUG = "" in your
# ``settings.py`` module, and delete the blog page object from the
# page tree in the admin if it was installed.
# url("^$", "mezzanine.blog.views.blog_post_list", name="home"),
# MEZZANINE'S URLS
# ----------------
# ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW.
# ``mezzanine.urls`` INCLUDES A *CATCH ALL* PATTERN
# FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.urls``
# WILL NEVER BE MATCHED!
# If you'd like more granular control over the patterns in
# ``mezzanine.urls``, go right ahead and take the parts you want
# from it, and use them directly below instead of using
# ``mezzanine.urls``.
("^", include("mezzanine.urls")),
# MOUNTING MEZZANINE UNDER A PREFIX
# ---------------------------------
# You can also mount all of Mezzanine's urlpatterns under a
# URL prefix if desired. When doing this, you need to define the
# ``SITE_PREFIX`` setting, which will contain the prefix. Eg:
# SITE_PREFIX = "my/site/prefix"
# For convenience, and to avoid repeating the prefix, use the
# commented out pattern below (commenting out the one above of course)
# which will make use of the ``SITE_PREFIX`` setting. Make sure to
# add the import ``from django.conf import settings`` to the top
# of this file as well.
# Note that for any of the various homepage patterns above, you'll
# need to use the ``SITE_PREFIX`` setting as well.
# ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))
)
# Adds ``STATIC_URL`` to the context of error pages, so that error
# pages can use JS, CSS and images.
handler404 = "mezzanine.core.views.page_not_found"
handler500 = "mezzanine.core.views.server_error"
You forgot to add the app's url.py to the root urls. Include the careers.urls like this:
urlpatterns += patterns('',
...
url("^$", direct_to_template, {"template": "index.html"}, name="home"),
...
("^careers/", include("careers.urls")),
...
("^", include("mezzanine.urls")),
...
)