Sitecore compare items version programmatically - sitecore

Lets suppose I have an Item with 5 versions. (I am not talking about language versions).
I would like to compare all the versions to identify the differencies. Is there some thing available out of box from Sitecore to do this task? Or I have have to loop over all the versions and then all the fields to find the differences.

No, there is nothing like that out of the box. You will have to compare fields one by one.
Remember that some of the fields should be ignored (like __Updated, __ValidFrom, __Workflow State, etc).
Remember that it's not easy to display what was changed in Blob fields.
And here is a code for you to start with:
FieldCollection fields = version1.Fields;
fields.ReadAll();
fields.Sort();
foreach (Field field1 in fields)
{
if (field1.ShouldBeTranslated)
{
Field field2 = version2.Fields[field1.ID];
var value1 = field1.Value;
var value2 = field2.Value;
... // whatever you need here
Make sure you add all the necessary null checks! I skipped them for the clarity.

Related

how to match a field name with another field name

I have two fields that run throughout a website that I would like to match so that when a user inputs a value either of the fields, it will match the other field. I'm using Sitecore Rocks and am trying to use a query to do this.
select ##h1#, ##Title#
from /sitecore/Content/Home//*[##h1# !="##Title#"];
update set ##h1# = ##Title# from /sitecore/Content/Home//*[##Title# = "<id>"];
What am I missing here?
This article talks about tapping in to the item:saving event which allows you to compare the fields values of the item before and after the changes:
http://www.sitecore.net/Community/Technical-Blogs/John-West-Sitecore-Blog/Posts/2010/11/Intercepting-Item-Updates-with-Sitecore.aspx
Using this, you can determine which field has been amended, then change the other to match.
I've had to do something similar to this when a new field was added, and we wanted to set the initial value equal to an existing field. It may be a bug in Sitecore Rocks, but I found it would only update a field when a static value was part of the query.
When I ran ##h1# = ##Title#, the query analyzer would return the correct number of items updated, but no values were actually updated. However, ##h1# = '<id>' worked perfectly. After trying a number of things, I found this did what I wanted.
update set ##h1# = '' + ##Title# from /sitecore/Content/Home//*[##Title# = "<id>"];
I hope that helps.

Sitecore Fast Query select attribute values

Is there a way by using XPath Builder under Developer Center inside Sitecore Shell (a Fast Query interface) to select a particular attribute from an item. Example:
/sitecore/content/Home/Products/*[##templatename = 'Product Group']/#id
I would expect to see a collection of id's to be returned where id is an attribute of an item. If yes is it possible to extract an attribute with a space bar? Example:
/sitecore/content/Home/Products/*[##templatename = 'Product Group']/#more info
EDIT
The thing that I want to achieve is to get a collection of items (I have few hounded items here), not one particular item. That's why I am not interested in adding additional conditions, like specific item id or title. I want to see a collection of values of a specific attribute. As in example showed above, I want to see a collection of values that are assign to 'more info' attribute. Once again I am expecting to see few hounded different values that are set to 'more info' attribute.
EDIT2
There is a problem with a production, a critical stuff. There is no access to it other then thru Sitecore shell, but I don't have permissions to add/install additional packages. I know how to get this info by implementing custom code, or queering db directly, but I simply do not have permission to do it. Guys that will be able to grant me need credentials will wake up in 6 hours, so I was hoping to do whatever I can to analyse the situation. I would accept Maras answer if it was an answer not a comment - there is no way I can do it using fast query. thanks for help.
Try using #
/sitecore/content/Home/Products/*[##templatename = 'Product Group']/##more info#
This is the way around when selecting items with fields that contain spaces. Having said that I don't know if you would be able to get a specific result or not for your specific question but give it a try.
For example, consider this query which returns Product S1
fast:/sitecore/content/home/*[#Title = 'Item 1' and ##templatename = 'Product Group1']//*[#Title = 'Product S1' and ##id = '{787EE6C5-0885-495D-855E-1D129C643E55}']
However, if you place the special attribute (i.e. ##id) at the beginning of the condition, the query will not return a result.
fast:/sitecore/content/home/*[##templatename = 'Product Group1' and #Title = 'Product S1']//*[##id = '{787EE6C5-0885-495D-855E-1D129C643E55}' and #Title = 'Product S1']
Remember this, Sitecore Fast Query only supports the following special attributes:
##id
##name
##key
##templateid
##templatename
##templatekey
##masterid
##parentid
Let us know if this helps.

How do I add a blank default option to a select widget?

I'm attempting to create a search page for a database that I am maintaining by creating a dynamically maintained select box of all of the unique values of a few of my fields.
After much time and thought, I've decided that the best way to create a search form for my database would be to do so in views, resulting in something equivalent to this:
search_form = modelform_facotry(my_model,
fields=('field_one', 'field_two',),
widgets={'field_one': Select(choices=((datum.field_one, datum.field_one) for datum in my_model.objects.distinct('field_one'))),
'field_two': Select(choices=((datum.field_two, datum.field_two) for datum in my_model.objects.distinct('field_two'))),
}
)
This works great! Except that I can't figure out how to include a blank option... The choices have to be created in a loop like that, so I can't just add a blank choice as many solutions suggest.
I've been pulling out my hair over this for a while now, because it seems like adding a blank option to a select widget would be an easy fix, but evidently not. Any help would be appreciated.
Edit: I should add that my fields are all CharFields
After playing around with it for a while, I discovered what I needed to do:
FIELD_ONE_CHOICES = (('', '-----'),)
for datum in my_model.objects.distinct('field_one'):
FIELD_ONE_CHOICES += ((datum.field_one, datum.field_one),)
FIELD_TWO_CHOICES = (('', '-----'),)
for datum in my_model.objects.distinct('field_two'):
FIELD_TWO_CHOICES += ((datum.field_two, datum.field_two),)
search_form = modelform_factory(my_model,
fields=('field_one', 'field_two'),
widgets={'field_one': Select(choices=FIELD_ONE_CHOICES),
'field_two': Select(choices=FIELD_TWO_CHOICES),
}
)
Tuples can be frustrating...

How to query for top 10 directories based on size?

I am very new to Django and I'm creating a simple app to track disk usage and show changes over time, etc.:
class Directory(models.Model):
path = models.CharField(max_length=200)
class Directory_Size(models.Model):
drivedir = models.ForeignKey(Directory, related_name = 'sizes')
measure_date = models.DateTimeField()
size = models.IntegerField()
Directory_Sizes stores the size of the directory and the time it was recorded. There will be many of these for each Directory.
How do I select the current size of the directory? I need the newest Directory_Size for each Directory.
How would I select the top 10 directories based on size, this would be a simple order by size and then limit to 10, can this be done by chaining the order_by and limit onto the top of the query above?
Should I change the models to make this type of thing easier?
I'm assuming this is simple and I don't know how because of my lack of Django knowledge.
This isn't related to your questions, but Django naming standards would tell you to name the model DirectorySize, not Directory_Size. You use either CamelCase or lowercase with underscores, not both (it's an xor). In general, classes (and therefore, models) are named using CamelCase. Function definitions and variables are lowercase with underscores.
source: https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/
1) Now my question is how do I select the current size of the directory. I need the newest Directory_Size for each directory.
d = Directory.objects.get( ...
d_size = d.sirectory_size_set.order_by( '-measure_date')[0].size
2) select the top 10 directories based on size: I think you need a custom raw query.
for p in Directory.objects.raw(
'SELECT *, (select ...) as s FROM myapp_directory order by s LIMIT 10'
)
Where (select ...) is a subquery to get actual size, also you can do a join ...
sizes will return a manager on which you can perform filtering operations. So this:
last_10_sizes = the_directory.sizes.order_by('-measure_date')[:10]
will return the latest 10 sizes.
Directory_Size.objects.all().order_by('-size')[:10]
However that is pretty crude and all objects.
You can filter on a mesure date as well and give a range, something like
import datetime
start_date = datetime.datetime(<values_here>)
end_date = datetime.datetime(<values_here>)
Directory_Size.objects.filter(measure_date__gte=start_date, measure_date__lte=end_date).order_by('-size')[:10]
do you need historical data, why not update the same dir and make it modified date with a default of of datetime.datetime.utc_now()?

Sitecore 6 - how to store html-formatted text and reference in codebehind

I would like to be able to store reusable html-formatted text in Sitecore and reference in codebehind for inclusion in a custom user control. What is the best practice for doing this? If a user selects option A, for example, I would reference standard text A in my control. Any examples for how to accomplish this are appreciated. Thanks.
You have a couple options:
Store the text in the Standard Values of the same template that defines your option list. That makes it available on the same item, but standard for all items. Use security to lock down the field if you are worried about it being edited. This could also be accomplished with the new "cloning" feature in 6.4, I believe.
Create a structure outside of your Home element for storing this data. Based on the option selected, find an item in your content tree which corresponds to the selected item, and read the text off of it. You would need to find this item either relative to /sitecore/Content, or relative to your website root if multi-site support is a requirement.
No.2 in pseudo-code:
//get the item where we have the text values
Item textBase = Sitecore.Context.Database.SelectSingleItem(textBasePath);
//find the child w/ the same name as the selected option
Item textItem = textBase.Axes.GetChild(selectedOptionValue);
string value = textItem["text"];
I think I would do something like techphoria414's 2. option:
ie you have your normal "page" templates as per usual, but then you have some fields (multilist, treelist fields), where you put the source pointing to your other items contain the different texts.
then you basically just have to get the items from the current item (with some very quick'n'dirty code/pseudocode):
var CurrentItem = Sitecore.Context.Item;
Sitecore.Data.Fields.MultilistField mlf1 = CurrentItem.Fields["myExternalTexts"];
if(mlf1 != null)
{
foreach (Item itm in mlf1.GetItems())
{
lit += Sitecore.Web.UI.WebControls.FieldRenderer.Render(itm, "richtext");
}
}
You ofc shouldn't just add them to a literal and you should you Sitecore built in Field renderes if using Sitecore 6 or above and it's a Rich text field.
I hope that helps.