Return template as string - Django - python

I'm still not sure this is the correct way to go about this, maybe not, but I'll ask anyway. I'd like to re-write wordpress (justification: because I can) albeit more simply myself in Django and I'm looking to be able to configure elements in different ways on the page. So for example I might have:
Blog models
A site update message model
A latest comments model.
Now, for each page on the site I want the user to be able to choose the order of and any items that go on it. In my thought process, this would work something like:
class Page(models.Model)
Slug = models.CharField(max_length=100)
class PageItem(models.Model)
Page = models.ForeignKey(Page)
ItemType = models.CharField(max_length=100) # tells me which model to display
InstanceNum = models.IntegerField() # tells me which instance of which model...
Then, ideally, my template would loop through all the PageItems in a page which is easy enough to do.
But what if my page item is a site update as opposed to a blog post? Basically, I am thinking I'd like to pull different item types back in different orders and display them using the appropriate templates. Now, I thought one way to do this would be to, in views.py, to loop through all of the objects and call the appropriate view function, return a bit of html as a string and then pipe that into the resultant template.
My question is - is this the best way to go about doing things? If so, how do I do it? If not, which way should I be going? I'm pretty new to Django so I'm still learning what it can and can't do, so please bear with me. I've checked SO for dupes and don't think this has been asked before...
I've also looked at Django-cms to see if that helps, but I couldn't get to grips with it.
Any suggestions?

First, some puzzelement.
InstanceNum = models.IntegerField() # all models have primary keys.
In Django, all model are assigned an integer primary key.
The comment doesn't make sense, since you don't need to add a primary key like this. The PageItem already has a primary key.
Also, please use lower case letters for attributes. Only Use Upper Case for Class Names. Please.
"But what if my page item is a site update as opposed to a blog post? Basically, I am thinking I'd like to
pull different item types back in
different orders and display them
using the appropriate templates"
Different types usually means different models. Rather than a vague "PageItem", you probably want to have "Site Update" and "Blog Post" as separate models.
You can then iterate through these various objects and display them in the template.
You can easily have your various Models defined with a method to return HTML information. You don't (generally) want to return fully-baked HTML. But CSS ID or Class information is sometimes helpful.
class SiteUpdate( models.Model ):
page = models.ForeignKey(Page)
item_text = models.CharField(max_length=100)
item_css_class = models.CharField(max_length=64)
Now you can generate this into the template with a simple <div class="{{item.item_css_class}}">{{item.item_text}}</div> and use CSS to handle the formatting details that distinguish site update as opposed to a blog post.

The include template tag can take a variable containing the template to include, so you could loop through a sequence containing the various sub-templates and include them in turn, maybe using a dict to map friendly names to template filenames.

Related

How can I add a changeable "subfield" to a ModelField in django?

I'm trying to create a kind of "subfield" for a CharField in django, but I'm not sure (a) if it is possible at all and (b) how to succeed if it is indeed possible.
Let's say I want a model for Tools. They would have a, e.g., a field for long_name, short_name, maybe a ForeignKey for realizing different departments. One of these tools I'd like to be a Link, the said "subfield" being a URLField with the href to the webpage.
Now, I can create multiple link entries with the associated URL, but I'd rather have only one tool called "Link" with the changing URL attached. Is this a case for ForeignKey as well? Does it make sense to have a model with only one field (well, two if you count the pkid) in it?
Or am I on a completely lost path here?
If I've understood you correctly, you want to have a number of links that can be attached to a Tool model, so instead of just having a single URLField you would have a Many-to-One relation with a Link model:
class ToolLink(models.Model):
url = models.URLField(...
class Tool(models.Model):
links = models.ForeignKey(ToolLink, ...
The problem is that you only want one particular tool to be able to hold links. Your options are to create a 'Tool' base model that then has multiple different types of tool, like 'StandardTool', 'LinkTool', etc. or to setup some logic that monitors whether the Tool has links or not (or if another tool already has links) and whether creating links is acceptable.

Should I use slug field too in django URLs?

I am developing an blog like application where there are going to be posts with similar or sometimes same titles. Also users are able to edit the titles of their post whenever they want.
Currently my urls look like this.
{{post.title}}
Now I've read few answers where along with id they have passed slug too like url of this question.
Even with id the url is going to be unique, right? then why slug? and if it is for humanizing the url then should be store it too?
So to summarize:
If id is unique then why slug?
If its important then should we store it?
If it has anything to do with canonical-link please elaborate the working of canonical links & how slug can help it? or at least direct me to the source.
Reference:
when to store slugfield in database in django?
and this answer
If id is unique then why slug?
Slug is just a way for you to quickly get a sense of what this URL is about - the readability of it which is not guaranteed by only using id.
If its important then should we store it?
URL of this question could be Should I use slug field too in django URLs? and still it redirects to same post. But having said that it also depends on the implementation. In this case it could be that Stack Overflow checks for a valid slug corresponding to the post ID and if not found then redirects to the original one.
I just changed the title of the question and as a result the URL changed as well:
old => http://stackoverflow.com/questions/42407755/should-i-use-slug-field-too-in-django
new => http://stackoverflow.com/questions/42407755/should-i-use-slug-field-too-in-django-urls
So if you store the slug you need to make sure it is updated everytime title is changed.
If it has anything to do with canonical-link please elaborate the working of canonical links & how slug can help it?
Canonical links are used by Search Engines to identify duplicate URLs which lead to same content. YOu can view to source code of this post and you can find following canonical link in the HEAD:
<link rel="canonical" href="http://stackoverflow.com/questions/42407755/should-i-use-slug-field-too-in-django-urls">
A search engine will collect this URL and return it to you when you search for some keywords which matches this URL. One of the factors based on which the search engine ranks the pages is matching keywords in URL. A good slug helps the search engine to return the user best results based on the matched keywords in the URL.
You need to identify a post by exactly 1 unique identifier. That can be either the ID or the slug. Using both is pointless and prone to errors. You can include both a slug and an id in the title, in which case you should probably just ignore the slug entirely passed in the URL and use the ID.
You can ignore the slug and just use the ID like this:
url(r'^(?:[\w-]+)/(?<id>\d+)/$', BlogView.as_view(), name='blog-view')
If you do that you don't need to store the slug at all, just generate it from the title each time you use it.
Personally, I prefer slugs because they provide friendlier URLs which integrate well with Django. For example with a class based view you can create a URL that looks like this:
url(r'^(?P<slug>[\w-]+)/$', BlogView.as_view(), name='blog-view')
And your class based view is super clean:
class BlogView(DetailView):
model=BlogEntry
That's it! Django automagically knows to look the model up by the slug and assuming you have your template named properly you don't need to wire anything else up (Ok you probably do). There is a really helpful gist on github about this setup.
If you want to use slugs, generate it when you save the record and use some kind of automatic mangling to make it unique if there is a collision (or let the user manually override it). In one of my blogs I incorporate the date in the slug to make it more unique then use a recursive function to ensure it's unique. (here's an little tutorial someone made on making unique slugs). It is a good idea to include some way to manually over-ride the slug also.
In the above link he uses a for loop, personally I prefer a recursive function such as:
def autoslug(self, slug, attempt=1):
if MyModel.objects.filter(slug=slug).exists():
return autoslug(slug[:47]+"%d" % attempt, attempt + 1)
else:
return slug
You create a slug field on the model to store the slug. For example, Class Based views can pass a slug and it will magically figure out what you want. Django's has a variety of internal tools that reference it by that name so keep it simple and use the same name django expects.
Also, the URL for a given resource should be unchanging so links are persistent. Changing a slug when you change the title means the URL for the resource changes, IMO it's always a bad idea for the same resource to have a changing URL. It's bad for SEO and bad for anyone who links your resources externally.

Global Variables in Django Admin Site

This was my original question, but it was not answered and so I thought Id post again with some of the strategies that I have tried, and be a little more specific.
I want to create a dynamic admin site, that based on if the field is blank or not will show that field. So I have a model that has a set number of fields, but for each individual entry will not contain all of the fields in my model and I want to exclude based on if that field is blank. My project is about bridges, and so to put it in practical terms I have a model that has every bridge part in it (this roughly is equivalent to 100), but each individual bridge (mapped to each unique brkey) will not have all 100 bridge parts. And so, I can prepopulate all of the fields it does have, but then the admin site has 100 other fields, and I would like to not display those fields that were not used on my admin site for that specific bridge, but those fields will differ with pretty much every bridge.
Like I said before, I have a unique bridge identifier(a unique 15 digit string), that correlates to each bridge, and then all of the various different variables that describe the bridge.
I have it set up now that the user will go to a url with the unique bridgekey and then this will create an entry of that bridge. So (as i am testing on my local machine) it would be like localhost/home/brkey and that code in my views.py that corresponds to that url is
Is this a final route that I have to take? I am very new to JavaScript and so I do not want to take this route but I will if I have to. Also does Django use Javascript in anyway that is syntactically different? If so I cannot find any Django documentation on incorporating Javascript into my admin site.
A final option that I have exhausted is to use global variables. Instead of having the url that creates the entry in my Views.py, I placed it in my admins.py, and had my modelAdmin class in there as well, so like this.
admins.py
-set up global variable
bridgekey_unique = " "
If I can find a way to either pass that unique bridge key to my modelAdmin class, or figure out if that said field is blank because the bridge doesnt have that part, I will be able to achieve what I want without using Javascript. I have tried a lot of variations of all two of theses strategies to no avail, but have not tried the JavaScript idea as I dont really know any javascript at all.
Sorry for the lengthy post, but people said I wasnt specific enough. Any help would be greatly appreciated.
I didn't read all of that - sorry, there's too much. But I did notice your comment that you expect to access in your modeladmin definition a variable that you set in your view. That can't possibly work.
Anything at class level is always executed when the module containing the class is first imported. That is when the server process starts up, so there is no possible way anything done in the view can have happened yet.
You almost never want to have any logic at class level. You need to put it in methods, which are called at the relevant time. In this case, you probably need to use the get_fields method.
Edit
Looking further up at your attempt at a get_fields method, I can't see at all what you are trying to do here. 'prestressed_concrete_deck' is a literal string, and could never be None, so neither of your conditions can ever be true. And as to your question about what the parameters are, the documentation for that method explains clearly that obj is the object being edited.

Django ModelField for an object that is the target of ForgeinKeys on other objects

I have some Django objects like this:
class Award(Model):
name = CharField(...)
date = DateTimeField(...)
class Book(Model):
name = CharField(...)
award = ForgeinKey(Award, blank=True)
(i.e. each Book may or may not have one award)
I want to make a form for adding/editing Awards. Assume lots of Books have already been created. Initially I created a ModelForm like this:
class AwardForm(ModelForm):
class Meta:
model = Award
which created a correct form with all the data, however there was no way to add books to the award (or mark this award as applicable to the books that were selected).
I was going to manually add a ModelMultipleChoiceField to the AwardForm (with a queryset for the Books), then add logic to is_valid that would check the Books that were selected, and add something to save to go through the selected Books and set the forgein key on that object to this object.
However, Is there a good 'django' way to do this automatically? i.e. just add a certain field to the Form which will do that all itself? If I were to change the Book.award to be a Award.books manytomany key it would probably do all this automatically, but I like the internal logic of having that as a forgeinkey on the Book.
I was just going to suggest using Inline's but upon re-reading your question the hard part is selecting objects that already exist and linking them to the Award that you are editing.
The way that you have suggested is the first way that I would do it, and the only other way I can think of would involve hacking away at some of the methods on your AwardAdmin to add in the functionality that you desire.
Using the ModelMultipleChoiceField though seems like quite a clean way of doing it to be honest, especially since you shouldn't really need much/any editing of the save method as the field should handle that itself?

In Django, searching and filter by searchbox and categories in one go?

I wonder if you could help me.
I have a list of data that will be displayed on one page. There is a simple search box, a list of categories and a list of tags that can all be used to filter the list of data. I'm trying to built it from the ground up (so it doesn't require JavaScript) but eventually it will submit the search criteria and return back a new list using Ajax.
So I have a list of categories in my database ('large', 'small', etc), and I have a list of tags in my database ('wooden', 'brass'). Tags are used to filter down more of what's in the categories. I then have a search box. Ideally, I want the user to effectively tick which categories they want, tick what tags they want and possibly put a search for keywords, and then submit all of that data so it can be queried and a new list of the filtered data can be returned.
I'm not a Django expert, and I'm stuck on how and where to do this... What is the Django way of spitting out the categories as a checkbox list, the tags as a checkbox list and the search box with a submit button... Which when submitted, I can take all that data and do the necessary queries on the database? I don't quite understand how I'd do this... I've been looking at the Django Docs and the Django Book for a few days and the way I'm doing things doesn't seem to be listed.
Please, any help at all would be fantastic.
spitting out the categories as a checkbox list,
the tags as a checkbox list and the
search box with a submit button...
This is a <form> in your HTML page. It probably doesn't match anything in the Django model very well. It's a unique form built more-or-less manually.
I can take all that data and do the necessary queries on the database?
That's a view function.
You'll probably have something like this.
objects= SomeModel.objects
if request.GET ... has categories ...
objects = objects.filter( ... categories ... )
if request.GET ... has tags ...
objects = objects.filter( ... tags ... )
if request.GET ... has search ...
objects = objects.filter( something__contains( search ) )
return render_to_response( ... etc. ... )
the way I'm doing things doesn't seem to be listed.
You're beyond the tutorial here.
What to do?
Do the ENTIRE tutorial. All the way through. Every step. It doesn't seem like it solves your problem, but you MUST do the ENTIRE tutorial.
Design your model. You didn't mention the model in the question. It's the absolutely most important and fundamental thing.
Create the default admin interface for that model. Get the default admin interface to work and do the kinds of things you'd like to do. It has great search, category and tag filtering.
In order to get the default admin to work, you'll need to design fairly sophisticated model and form features. You'll probably have to add method functions to your model as well as choice items and other goodness.
AFTER you have the admin page pretty close to what you want, you can write you own customized view.
each single checkbox has a different name ('category_option_1', 'category_option_2', etc.) ... How do I read these? I can't just put request.POST['category_option_n']?
Really? Why didn't your question say that?
Are you asking about this?
for k in range(1024):
name = 'category_option_{0}'.format(k)
# Use request.POST.get(name,None) to build a `Q` object

Categories