Django schedule: Difference between event.get_occurrence() and event.get_occurrences()? - django

Based on django-schedule. I can't find the guy who made it.
Pardon me if I'm missing something, but I've been trying to get an events occurrences, preferably for a given day.
When I use event.get_occurrence(date), it always returns nothing. But when I use event.get_occurrences(before_date, after_date), suddenly the occurrences on the previously attempted date show up.
Why won't this work with just one datetime object?

This difference is probably in the actual design of these two methods. Frankly, get_occurrence is rather flawed, in general. A method like this should always return something, even if it's just None, but there's scenarios where it doesn't return at all. Namely, if your event doesn't have an rrule, and the date you passed get_occurrence isn't the same as your event's start, then no value is returned.
There's not really anything that can be done about that. It's just flawed code.

Based on the above comment especially in the case when the event doesn't return and occurrence, the following snippet below can force the retrieval of an occurrence especially when you are sure that it exists
from dateutil.relativedelta import relativedelta
def custom_get_occurrence(event,start_date):
occurrence = event.get_occurrence(start_date)
if occurrence is None:
occurrences = event.get_occurrences(start_date, start_date+relative_delta(months=3)
result = filter(lambda x: x.start==start_date,occurrences)
occurence = result[0]
The above code resolves issue that might occur when the default get_occurrence doesn't return a result.

Related

Django: Query gives zero results after first match in for loop

The following code works fine until the filter gets first match(es). After that on the following runs in the for loop, the query always returns 0. If in that result object would be a match for the next row also, it doesn't even see that, so I don't see this being a cache issue (which might have been far fetched anyhow).
for row in self._ordr.OrderRows.SalesOrderRow:
available = row.Row_amount - Slot.objects.filter(rows_ids=row.Row_id).count()
if available > 0 or row.Row_id in self.instance.rows_ids:
# some code
Any ideas what am I doing wrong here?
This is the models code on that rows_ids.
from django.db import models
from django_mysql.models import ListCharField
class Slot(models.Model):
rows_ids = ListCharField(base_field=models.IntegerField(), size=10, max_length=(10 * 21), null=True)
Went through the documentation once more, and apparently it's a ListCharField based issue. To find a match in all the options in it, you shouldn't compare it directly to the field, but rather to field__contains. So the correct code is:
for row in self._ordr.OrderRows.SalesOrderRow:
available = row.Row_amount - Slot.objects.filter(rows_ids__contains=row.Row_id).count()
if available > 0 or row.Row_id in self.instance.rows_ids:
# some code
Finally got it to work with this.

Filter objects or (if 0 found) get all objects in Django with one DB hit

Is there a way in Django to achieve the following in one DB hit (Debug Toolbar shows 2 queries)?
q = SomeModel.objects.filter(name=name).order_by(some_field)
if q.count() == 0:
q = SomeModel.objects.all().order_by(some_field)
I want to check if there are objects with a given name. If yes, then return them. If not, return all objects. All done in one query.
I've checked Subquery, Q, conditional expressions but still don't see how to fit it into one query.
Ok, much as I resisted (I still think it's premature optimization), curiosity got the better of me. This is not pretty but does the trick:
from django.db.models import Q, Exists
name_qset = SomeObject.objects.filter(name=name)
q_func = Q(name_exists=True, name=name) | Q(name_exists=False)
q = SomeModel.objects.annotate(
name_exists=Exists(name_qset)
).filter(q_func).order_by(some_field)
Tried it out and definitely only one query. Interesting to see if it is actually appreciably faster for large datasets...
You best bet is to use .exists(), otherwise your code is fine
q = SomeModel.objects.filter(name=name).order_by(some_field)
if not q.exists():
q = SomeModel.objects.all().order_by(some_field)

filter output of subprocess.check_output

I'm trying to match values of a list to a regex pattern. If the particular value within the list matches, I'll append it to a different list of dicts. If the above mentioned value does not match, I want to remove the value from the list.
import subprocess
def list_installed():
rawlist = subprocess.check_output(['yum', 'list', 'installed']).splitlines()
#print rawlist
for each_item in rawlist:
if "[\w86]" or \
"noarch" in each_item:
print each_item #additional stuff here to append list of dicts
#i haven't done the appending part yet
#the list of dict's will be returned at end of this funct
else:
remove(each_item)
list_installed()
The end goal is to eventually be able to do something similar to:
nifty_module.tellme(installed_packages[3]['version'])
nifty_module.dosomething(installed_packages[6])
Note to gnu/linux users going wtf:
This will eventually grow into a larger sysadmin frontend.
Despite the lack of an actual question in your post, I'll make a couple of comments.
You have a problem here:
if "[\w86]" or "noarch" in each_item:
It's not interpreted the way you think of it and it always evaluates to True. You probably need
if "[\w86]" in each_item or "noarch" in each_item:
Also, I'm not sure what you are doing, but in case you expect that Python will do regex matching here: it won't. If you need that, look at re module.
remove(each_item)
I don't know how it's implemented, but it probably won't work if you expect it to remove the element from rawlist: remove won't be able to actually access the list defined inside list_installed. I'd advise to use rawlist.remove(each_item) instead, but not in this case, because you are iterating over rawlist. You need to re-think the procedure a little (create another list and append needed elements to it instead of removing, for example).

Django queryset to match all related objects

Let's say I have a ForeignKey from Coconut to Swallow (ie, a swallow has carried many coconuts, but each coconut has been carried by only one swallow). Now let's say that I have a ForeignKey from husk_segment to Coconut.
Now, I have a list of husk_segments and I want to find out if ALL of these have been carried gripped by a particular swallow.
I can have swallow.objects.filter(coconuts_carried__husk_sements__in = husk_segment_list) to show that this swallow has gripped at least one husk segment in the list. Now, how can I show that every husk segment that the swallow has ever carried are in this list?
I can have swallow.objects.filter(coconuts_carried__husk_sements__in =
husk_segment_list) to show that this swallow has gripped at least one
husk segment in the list.
No, this is wrong, this gives you a list of swallows which have carried at least one husk segment from *husk_segment_list*.
If I've understood right, we are talking about checking for a specific swallow.
So, from your description I guess your models look something like this:
class Swallow(models.Model):
name = models.CharField(max_length=100)
class Coconut(models.Model):
swallow = models.ForeignKey(Swallow, related_name='coconuts_carried')
class HuskSegment(models.Model):
coconut = models.ForeignKey(Coconut, related_name='husk_segments')
If you already have the husk segment list you need to check againts the swallows segments, there's no reason you need to resolve it in a query. Get the swallows' segments and check if it's a superset of your husk segment list.
So we have:
#husk_segment_list = [<object: HuskSegment>, <object: HuskSegment>, <object: HuskSegment>...]
husk_segments_set = set((husk.pk for husk in husk_segment_list))
whitey = Swallow.object.get(name='Neochelidon tibialis')
wh_segments_set = set((value[0] for value in HuskSegment.objects.filter(coconut__in=whitey.coconuts_carried.all()).values_list('id')))
whitey_has_carried_all = wh_segments_set.issuperset(husk_segments_set)
See the docs on queries spanning multi-valued relationships -- you should chain filter calls.
A simple way to go would be something like
queryset = Swallow.objects.all()
for coconut in coconuts:
queryset = queryset.filter(coconuts_carried=coconut)
A fancy way to do this in one line using reduce would be
reduce(lambda q, c: q.filter(coconuts_carried=c), coconuts, Swallow.objects.all())
If i understood your altered question correctly you should be able to compare the coconut_carried_set of the swallow with the list of coconuts that have been carried.
see docs
I'm not entirely sure that this is what you want - I guess it depends on if you know which swallow you want to check beforehand or if you want to check it against all swallows - in that case there may be a better solution.

How to make this django attribute name search better?

lcount = Open_Layers.objects.all()
form = SearchForm()
if request.method == 'POST':
form = SearchForm(request.POST)
if form.is_valid():
data = form.cleaned_data
val=form.cleaned_data['LayerName']
a=Open_Layers()
data = []
for e in lcount:
if e.Layer_name == val:
data = val
return render_to_response('searchresult.html', {'data':data})
else:
form = SearchForm()
else:
return render_to_response('mapsearch.html', {'form':form})
This just returns back if a particular "name" matches . How do to change it so that it returns when I give a search for "Park" , it should return Park1 , Park2 , Parking , Parkin i.e all the occurences of the park .
You can improve your searching logic by using a list to accumulate the results and the re module to match a larger set of words.
However, this is still pretty limited, error prone and hard to maintain or even harder to make evolve. Plus you'll never get as nice results as if you were using a search engine.
So instead of trying to manually reinvent the wheel, the car and the highway, you should spend some time setting up haystack. This is now the de facto standard to do search in Django.
Use woosh as a backend at first, it's going to be easier. If your search get slow, replace it with solr.
EDIT:
Simple clean alternative:
Open_Layers.objects.filter(name__icontains=val)
This will perform a SQL LIKE, adding %` for you.
This going to kill your database if used too often, but I guess this is probably not going to be an issue with your current project.
BTW, you probably want to rename Open_Layers to OpenLayers as this is the Python PEP8 naming convention.
Instead of
if e.Layer_name == val:
data = val
use
if val in e.Layer_name:
data.append(e.Layer_name)
(and you don't need the line data = form.cleaned_data)
I realise this is an old post, but anyway:
There's a fuzzy logic string comparison already in the python standard library.
import difflib
Mainly have a look at:
difflib.SequenceMatcher(None, a='string1', b='string2', autojunk=True).ratio()
more info here:
http://docs.python.org/library/difflib.html#sequencematcher-objects
What it does it returns a ratio of how close the two strings are, between zero and 1. So instead of testing if they're equal, you chose your similarity ratio.
Things to watch out for, you may want to convert both strings to lower case.
string1.lower()
Also note you may want to impliment your favourite method of splitting the string i.e. .split() or something using re so that a search for 'David' against 'David Brent' ranks higher.