Here is a url containing the hash for a super-secret feed:
http://127.0.0.1:8000/something/feed/12e8e59187c328fbe5c48452babf769c/
I am trying to capture and send the variable '12e8e59187c328fbe5c48452babf769c' which is feed_hash (acts as a slug to retrieve the particular entry)
Based on the example in django-syndication, I've created this simple class in feeds.py
class SomeFeed(Feed):
title = 'feed title '+request.feed_hash #just testing
link = "/feed/"
description = "Feed description"
def items(self):
return Item.objects.order_by('-published')[:5]
def item_title(self, item):
return item.title
def item_description(self, item):
return item.content
# item_link is only needed if NewsItem has no get_absolute_url method.
def item_link(self, item):
return 'link'
Hence I am wondering, how would I modify this to get a model according to the hash?
At this time I cannot access the 12e8e59187c328fbe5c48452babf769c in any way. How might I access this and -- in a standard Django way -- create a feed from the retrieved variable (which represents a slug accessing a many-to-many relationship.)
First of all, set your parameter in django URL dispatcher. Something like:
url(r'^feed/(?P<pid>\w+)/$', SomeFeed())
Now retrieve and return the hash from the URL using the get_object method on your feed class. After all, get the hash as the second parameter of your method items().
class SomeFeed(Feed):
def get_object(self, request, pid):
# expect pid as your second parameter on method items()
return pid
# you can also load an instance here and get it the same way on items()
return SomeFeed.objects.get(pk=pid)
def items(self, feed):
# filter your feed here based on the pid or whatever you need..
return Item.objects.filter(feed=feed).order_by('-published')[:5]
Related
I want to generate a table on my template, showing some data that I get from a method declared on my Task class
models.py
class Task(models.Model):
...
def check_if_finished(self):
resp = requests.get(
'http://my.rest.api/tasks/view/{}'.format(self.task_id))
resp_data = resp.json()
resp_finished = resp_data['task']['started_on']
if resp_finished is None:
return False
else:
return resp_finished
I know that there is no sense in calling a method on template, but what do I need to use to show this data?
template.html
{{ task.is_finished(task.task_id) }}
When you write a model method you pass on self as parameter, which obviously refers to instance itself. Change your model method to something like this
class Task(models.Model):
fields
def is_finished(self):
return appropriate boolean from here
Now in your template you can use this simply as {{ task.is_finished }}. Notice that I am not passing any id as a parameter. This is because, when writing a model method you pass self as parameter which refers to instance on which method is being called.
I hope this makes sense to you and helps you understand model methods in a simple way.
I don't fully understand your question, why can't you just sent in task_id as a parameter?
class Task(models.Model):
...
def check_if_finished(self, task_id):
resp = requests.get(
'http://my.rest.api/tasks/view/{}'.format(task_id))
resp_data = resp.json()
resp_finished = resp_data['task']['started_on']
if resp_finished is None:
return False
else:
return resp_finished
then call it anytime:
{{ task.check_if_finished(task.task_id) }}
Could also make task_id an optional parameter.
def check_if_finished(self, task_id=None):
task_id = task_id or self.task_id
resp = requests.get...
I'm not sure why you wouldn't want to use the task_id on the instance though. If you never will then maybe it should be a static method?
#staticmethod
def check_if_finished(cls, task_id):
...
I don't think Django models prevent any of these options. Hopefully something there was helpful, else I need a bit more information and what you are trying to accomplish.
Edit: Django templates don't allow calling function/methods with arguments. You need to create a custom template tag or just call the function in the view and send the result to the template. See previous question.
So using Google Cloud Endpoints, we can create a custom request message and create a endpoints.ResourceContainer from it, like this:
Test_Resource = endpoints.ResourceContainer(message_types.VoidMessage,
param1=messages.IntegerField(2, required=False),
param2=messages.StringField(3, required=False))
And then later on use that in our endpoints.method
#endpoints.method(Test_Resource, MessageCommon, path='list', http_method='POST', name='list')
def model_list(self, request):
pass
My question is that is there any way that we can dynamically create the ResourceContainer by passing a dictionary contains messages types. Something like a factory to create ResourceContainer:
def get_resource_container(messageCls, dict):
new_rc = endpoints.ResourceContainer(messageCls)
# How do I add in the dict's properties to the ResourceContainer here
# ...
return new_rc
This will help not to create new Message class every time. We can keep reuse the same base class:
Test_RC2 = get_resource_container(message.types.VoidMessage, dict)
#endpoints.method(Test_RC2, MessageCommon, path='list', http_method='POST', name='list')
def model_list(self, request):
pass
I tried to search the detail of ResourceContainer but seems like none is available.
Is this possible at all ?
If you want to transform a dict to a list of named parameters you can do : endpoints.ResourceContainer(messageCls, **dict)
I have custom ZIPCodeField, but it require country to be given to work properly,
it's easy for validation where i can just save it in _country attribute of the form in form's init(with fallback to country field in the same form), it looks like:
class ZIPCodeField(wtforms.TextField):
def pre_validate(self, form):
if not self.data:
return
country = country = getattr(form, '_country', form.data.get('country'))
country = country.upper()
if not validate_zip_code(self.data, country):
raise ValueError(self.gettext(u'Invalid ZIP code.'))
but there is a problem with for process_formdata method (where I want to pass the received data trough simple filter to format the ZIP code correctly), we have no form instance, so seems like there are 2 solutions:
Saving country on field level, like:
class ZIPCodeField(wtforms.TextField):
def process_formdata(self, valuelist):
if valuelist:
self.data = format_zip_code(valuelist[0], self._country)
else:
self.data = ''
class TestForm(wtforms.Form):
zip_code = ZIPCodeField()
form = TestForm(MultiDict([('zip_code', '123455')]))
form.zip_code._country = u'US'
Or, overide process method and pass my extra value to it's data argument, like:
class ZIPCodeField(wtforms.TextField):
def process(self, formdata, data):
# we picking country value from data here
pass
form = TestForm(MultiDict([('zip_code', '123455')]),
zip_code=zip_code={'country': u'US'})
Which of these is proper solution? or there is better solution?
All of them will work but in general I would advise you too keep data access logic out of your forms. This makes for a bad separation of concerns.
You forms have a very specific job and that is to validate the form submission. In your case you want to augment the data submitted in form then validate it. This doesn't require any overriding of wtforms process methods. I would do the country retrieval either in a middleware or in the view, append it to the form's submission data, then validate the form as normal. If the zipcode didn't return a valid country or wasn't found I would abort(400) right there.
I have a view that filters the field called "defaultfieldname" in a certain object_list. What I want to do is to adapt it to pass the name of the field as as parameter in urls.py, so I could use different urls for different fields.
I am not sure which way would be easier:
url(r'^calendar/birthday/$', login_required(MonthCalends.as_view(model=Person)), name='bday_list', filter_field="birthdate"),
url(r'^calendar/deathday/$', login_required(MonthCalends.as_view(model=Person)), name='dday_list', filter_field="deathdate"),
or
url(r'^calendar/birthday/$', login_required(MonthCalends.as_view(model=Person, filter_field="birthdate")), name='bday_list'),
url(r'^calendar/deathday/$', login_required(MonthCalends.as_view(model=Person, filter_field="deathdate")), name='dday_list'),
Then I have a view:
class MonthCalends(ListView):
template_name='month_list.html'
## Sets default fieldname value
filter_field = "defaultfieldname"
...rest of code
The param in urls.py should overwrite the "defaultfieldname" on the view, but I don't know how to get the filter_field from the urls.py in the view. Any help?
Thanks!
The arguments you send with as_view are set on the MonthCalends object. That means filter_field is available as self.filter_field. Assuming you have defined the get method you could do as follows:
class MonthCalends(ListView):
template_name='month_list.html'
## Sets default fieldname value
filter_field = "defaultfieldname"
def get(self, request, *args, **kwargs):
try:
# if the filter field was sent as an argument
filter_field = self.filter_field
except:
# else revert to default
filter_field = MonthCalends.filter_field
# ...rest of code
For a more full explanation check the Django class based views documentation.
You may just use one url, that triggers the second part of your url:
url(r'^calendar/(\w+)$', login_required(MonthCalends.as_view(model=Person)), name='bday_list'),
Then you may access it using self.args[0]
And in case you just permit two different types for filter_field, you may just raise an exception later in the class that you have read self.args[0].
Of course, you may use more readable syntax in the regex like:
r'^calendar/(?P<type>\w+)$'
In this case you can access it using self.kwargs['type'].
Anyway, using regex groups seems much neater.
What does resolve_variable do? And could I use it for accessing the request outside of the view?
Edit
So template.Variable is the correct way to go - but I'm still unsure of its purpose. The documentation doesn't really help.
Cheers guys.
I'm assuming your trying to write a custom template tag here, so here's what you do.
In your compilation function, you bind the variable like so:
#register.tag
def my_tag(parser, token):
# This version uses a regular expression to parse tag contents.
try:
# Splitting by None == splitting by spaces.
tag_name, var_name = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
#this will "bind" the variable in the template to the actual_var object
actual_var = template.Variable(var_name)
return MyNode(template_variable)
class MyNode(template.Node):
def __init__(self, actual_var):
self.actual_var = actual_var
def render(self, context):
actual_var_value = self.actual_var.resolve(context)
#do something with it
return result
If you only want access the request, you bind against the variable directly in the node. Make sure you have the request in the context:
from django.template import RequestContext
def my_view(request):
#request stuff
return render_to_response("mytemplate.html", {'extra context': None,}, context_instance=RequestContext(request))
Then in your template tag code.
#register.tag
def simple_request_aware_tag(parser, token):
return SimpleRequestAwareNode()
class SimpleRequestAwareNode(template.Node):
def render(self, context):
request = template.Variable('request').resolve(context)
#we want to return the current username for example
return request.user.get_full_name()
what does resolve_variable do
Resolves a variable in a template tag.
could I use it for accessing the request outside of the view
In a template tag? Yes, as long as the request is in the context - but you don't necessarily need resolve_variable for that, if you're using a simple tag or inclusion tag.